maya-umbrella 0.5.0__py2.py3-none-any.whl → 0.6.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of maya-umbrella might be problematic. Click here for more details.
- maya_umbrella/__init__.py +6 -2
- maya_umbrella/__version__.py +1 -1
- maya_umbrella/cleaner.py +111 -0
- maya_umbrella/collector.py +411 -0
- maya_umbrella/constants.py +4 -0
- maya_umbrella/defender.py +161 -0
- maya_umbrella/filesystem.py +90 -3
- maya_umbrella/i18n.py +76 -0
- maya_umbrella/locales/en_US.json +19 -0
- maya_umbrella/locales/zh_CN.json +19 -0
- maya_umbrella/maya_funs.py +102 -2
- maya_umbrella/scanner.py +101 -0
- maya_umbrella/signatures.py +10 -0
- maya_umbrella/vaccine.py +18 -234
- maya_umbrella/vaccines/vaccine1.py +2 -1
- maya_umbrella/vaccines/vaccine2.py +14 -14
- maya_umbrella/vaccines/vaccine3.py +24 -16
- {maya_umbrella-0.5.0.dist-info → maya_umbrella-0.6.0.dist-info}/METADATA +66 -4
- maya_umbrella-0.6.0.dist-info/RECORD +28 -0
- maya_umbrella/core.py +0 -120
- maya_umbrella-0.5.0.dist-info/RECORD +0 -21
- {maya_umbrella-0.5.0.dist-info → maya_umbrella-0.6.0.dist-info}/LICENSE +0 -0
- {maya_umbrella-0.5.0.dist-info → maya_umbrella-0.6.0.dist-info}/WHEEL +0 -0
maya_umbrella/vaccine.py
CHANGED
|
@@ -1,238 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import glob
|
|
4
|
-
import logging
|
|
5
|
-
import os
|
|
6
|
-
import re
|
|
7
|
-
|
|
8
|
-
# Import local modules
|
|
9
|
-
from maya_umbrella.constants import FILE_VIRUS_SIGNATURES
|
|
10
|
-
from maya_umbrella.filesystem import remove_virus_file_by_signature
|
|
11
|
-
from maya_umbrella.filesystem import safe_remove_file
|
|
12
|
-
from maya_umbrella.filesystem import safe_rmtree
|
|
13
|
-
from maya_umbrella.maya_funs import check_reference_node_exists
|
|
14
|
-
from maya_umbrella.maya_funs import cmds
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class MayaVirusCleaner(object):
|
|
18
|
-
_bad_files = []
|
|
19
|
-
_infected_files = []
|
|
20
|
-
_bad_nodes = []
|
|
21
|
-
_bad_script_nodes = []
|
|
22
|
-
_bad_script_jobs = []
|
|
23
|
-
_registered_callbacks = defaultdict(list)
|
|
24
|
-
_fix_funcs = []
|
|
25
|
-
|
|
26
|
-
def __init__(self, logger=None, auto_fix=True):
|
|
27
|
-
self.logger = logger or logging.getLogger(__name__)
|
|
28
|
-
self.auto_fix = auto_fix
|
|
29
|
-
|
|
30
|
-
@property
|
|
31
|
-
def user_app_dir(self):
|
|
32
|
-
"""Return the user application directory."""
|
|
33
|
-
return cmds.internalVar(userAppDir=True)
|
|
34
|
-
|
|
35
|
-
@property
|
|
36
|
-
def maya_file(self):
|
|
37
|
-
"""Return the current Maya file."""
|
|
38
|
-
return cmds.file(query=True, sceneName=True, shortName=True) or "empty/scene"
|
|
39
|
-
|
|
40
|
-
@property
|
|
41
|
-
def maya_install_root(self):
|
|
42
|
-
"""Return the Maya installation root directory."""
|
|
43
|
-
return os.environ["MAYA_LOCATION"]
|
|
44
|
-
|
|
45
|
-
@property
|
|
46
|
-
def user_script_path(self):
|
|
47
|
-
"""Return the user script directory."""
|
|
48
|
-
return cmds.internalVar(userScriptDir=True)
|
|
49
|
-
|
|
50
|
-
@property
|
|
51
|
-
def local_script_path(self):
|
|
52
|
-
"""Return the local script directory."""
|
|
53
|
-
return os.path.join(self.user_app_dir, "scripts")
|
|
54
|
-
|
|
55
|
-
@property
|
|
56
|
-
def bad_files(self):
|
|
57
|
-
"""Return a list of bad files."""
|
|
58
|
-
return [path for path in list(set(self._bad_files)) if os.path.exists(path)]
|
|
59
|
-
|
|
60
|
-
@property
|
|
61
|
-
def bad_nodes(self):
|
|
62
|
-
"""Return a list of bad nodes."""
|
|
63
|
-
return list(set(self._bad_nodes))
|
|
64
|
-
|
|
65
|
-
@property
|
|
66
|
-
def bad_script_nodes(self):
|
|
67
|
-
"""Return a list of bad script nodes."""
|
|
68
|
-
return list(set(self._bad_script_nodes))
|
|
69
|
-
|
|
70
|
-
@property
|
|
71
|
-
def bad_script_jobs(self):
|
|
72
|
-
"""Return a list of bad script jobs."""
|
|
73
|
-
return list(set(self._bad_script_jobs))
|
|
74
|
-
|
|
75
|
-
@property
|
|
76
|
-
def infected_files(self):
|
|
77
|
-
return self._infected_files
|
|
78
|
-
|
|
79
|
-
def callback_remove_rename_temp_files(self, *args, **kwargs):
|
|
80
|
-
"""Remove temporary files in the local script path."""
|
|
81
|
-
self.logger.info("Removing temporary files in %s", self.local_script_path)
|
|
82
|
-
for temp_file in glob.glob(os.path.join(self.local_script_path, "._*")):
|
|
83
|
-
safe_remove_file(temp_file)
|
|
84
|
-
|
|
85
|
-
@property
|
|
86
|
-
def registered_callbacks(self):
|
|
87
|
-
return self._registered_callbacks
|
|
88
|
-
|
|
89
|
-
def add_infected_files(self, files):
|
|
90
|
-
self._infected_files.extend(files)
|
|
91
|
-
|
|
92
|
-
def add_infected_file(self, file):
|
|
93
|
-
self._infected_files.append(file)
|
|
94
|
-
|
|
95
|
-
def add_bad_files(self, files):
|
|
96
|
-
self._bad_files.extend(files)
|
|
97
|
-
|
|
98
|
-
def add_bad_file(self, file):
|
|
99
|
-
self._bad_files.append(file)
|
|
100
|
-
|
|
101
|
-
def add_bad_nodes(self, nodes):
|
|
102
|
-
self._bad_nodes.extend(nodes)
|
|
103
|
-
|
|
104
|
-
def add_bad_node(self, node):
|
|
105
|
-
self._bad_nodes.append(node)
|
|
106
|
-
|
|
107
|
-
def add_bad_script_jobs(self, jobs):
|
|
108
|
-
self._bad_script_jobs.extend(jobs)
|
|
109
|
-
|
|
110
|
-
def add_bad_script_job(self, job):
|
|
111
|
-
self._bad_script_jobs.append(job)
|
|
112
|
-
|
|
113
|
-
def add_bad_script_nodes(self, nodes):
|
|
114
|
-
self._bad_script_nodes.extend(nodes)
|
|
115
|
-
|
|
116
|
-
def add_bad_script_node(self, node):
|
|
117
|
-
self._bad_script_nodes.append(node)
|
|
118
|
-
|
|
119
|
-
def register_callback(self, callback_name, callback):
|
|
120
|
-
"""Register a callback to be executed before or after processing."""
|
|
121
|
-
self._registered_callbacks[callback_name].append(callback)
|
|
122
|
-
|
|
123
|
-
def add_after_open_callback(self, callback):
|
|
124
|
-
self.register_callback("after_open", callback)
|
|
125
|
-
|
|
126
|
-
def add_maya_initialized_callback(self, callback):
|
|
127
|
-
self.register_callback("maya_initialized", callback)
|
|
128
|
-
|
|
129
|
-
def add_after_import_callback(self, callback):
|
|
130
|
-
self.register_callback("after_import", callback)
|
|
131
|
-
|
|
132
|
-
def add_after_import_reference_callback(self, callback):
|
|
133
|
-
self.register_callback("after_import_reference", callback)
|
|
134
|
-
|
|
135
|
-
def add_after_load_reference_callback(self, callback):
|
|
136
|
-
self.register_callback("after_load_reference", callback)
|
|
137
|
-
|
|
138
|
-
def add_before_save_callback(self, callback):
|
|
139
|
-
self.register_callback("before_save", callback)
|
|
140
|
-
|
|
141
|
-
def add_before_import_callback(self, callback):
|
|
142
|
-
self.register_callback("before_import", callback)
|
|
143
|
-
|
|
144
|
-
def add_before_load_reference_callback(self, callback):
|
|
145
|
-
self.register_callback("before_load_reference", callback)
|
|
146
|
-
|
|
147
|
-
def add_before_import_reference_callback(self, callback):
|
|
148
|
-
self.register_callback("before_import_reference", callback)
|
|
149
|
-
|
|
150
|
-
def add_maya_exiting_callback(self, callback):
|
|
151
|
-
self.register_callback("maya_exiting", callback)
|
|
152
|
-
|
|
153
|
-
def setup_default_callbacks(self):
|
|
154
|
-
self.add_maya_initialized_callback(self.callback_remove_rename_temp_files)
|
|
155
|
-
self.add_maya_exiting_callback(self.callback_remove_rename_temp_files)
|
|
156
|
-
|
|
157
|
-
def add_fix_function(self, func):
|
|
158
|
-
self._fix_funcs.append(func)
|
|
159
|
-
|
|
160
|
-
def fix_script_jobs(self):
|
|
161
|
-
for script_job in self.bad_script_jobs:
|
|
162
|
-
script_num = int(re.findall(r"^(\d+):", script_job)[0])
|
|
163
|
-
self.logger.info("Kill script job %s", script_job)
|
|
164
|
-
cmds.scriptJob(kill=script_num, force=True)
|
|
165
|
-
self._bad_script_jobs.remove(script_job)
|
|
166
|
-
|
|
167
|
-
def fix_bad_files(self):
|
|
168
|
-
for file_ in self.bad_files:
|
|
169
|
-
if os.path.exists(file_):
|
|
170
|
-
if os.path.isfile(file_):
|
|
171
|
-
self.logger.info("Removing %s", file_)
|
|
172
|
-
safe_remove_file(file_)
|
|
173
|
-
self._bad_files.remove(file_)
|
|
174
|
-
else:
|
|
175
|
-
self.logger.info("Removing folder %s", file_)
|
|
176
|
-
safe_rmtree(file_)
|
|
177
|
-
self._bad_files.remove(file_)
|
|
178
|
-
|
|
179
|
-
def fix_bad_nodes(self):
|
|
180
|
-
for node in self.bad_nodes:
|
|
181
|
-
self.logger.info("Deleting %s", node)
|
|
182
|
-
is_referenced = check_reference_node_exists(node)
|
|
183
|
-
if is_referenced:
|
|
184
|
-
try:
|
|
185
|
-
cmds.setAttr("{node}.before".format(node=node), "", type="string")
|
|
186
|
-
cmds.setAttr("{node}.after".format(node=node), "", type="string")
|
|
187
|
-
cmds.setAttr("{node}.scriptType".format(node=node), 0)
|
|
188
|
-
self._bad_nodes.remove(node)
|
|
189
|
-
except Exception as e:
|
|
190
|
-
self.logger.debug(e)
|
|
191
|
-
else:
|
|
192
|
-
try:
|
|
193
|
-
cmds.lockNode(node, lock=False)
|
|
194
|
-
except ValueError:
|
|
195
|
-
pass
|
|
196
|
-
try:
|
|
197
|
-
cmds.delete(node)
|
|
198
|
-
except ValueError:
|
|
199
|
-
pass
|
|
200
|
-
self._bad_nodes.remove(node)
|
|
201
|
-
|
|
202
|
-
def fix_infected_files(self):
|
|
203
|
-
for file_path in self.infected_files:
|
|
204
|
-
self.logger.info("Removing infected file: %s", file_path)
|
|
205
|
-
remove_virus_file_by_signature(file_path, FILE_VIRUS_SIGNATURES)
|
|
206
|
-
self._infected_files.remove(file_path)
|
|
207
|
-
|
|
208
|
-
def fix_all_issues(self):
|
|
209
|
-
"""Fix all issues related to the Maya virus."""
|
|
210
|
-
self.logger.info("Starting Fixing all issues related to the Maya virus from %s.", self.maya_file)
|
|
211
|
-
self.fix_bad_files()
|
|
212
|
-
self.fix_infected_files()
|
|
213
|
-
self.fix_bad_nodes()
|
|
214
|
-
self.fix_script_jobs()
|
|
215
|
-
for func in self._fix_funcs:
|
|
216
|
-
func()
|
|
217
|
-
self.logger.info("Finished Fixing all issues related to the Maya virus from %s.", self.maya_file)
|
|
218
|
-
|
|
219
|
-
def report_all_issues(self):
|
|
220
|
-
"""Report all issues related to the Maya virus."""
|
|
221
|
-
self.logger.info("Bad files: %s", self.bad_files)
|
|
222
|
-
self.logger.info("Bad nodes: %s", self.bad_nodes)
|
|
223
|
-
self.logger.info("Bad script jobs: %s", self.bad_script_jobs)
|
|
224
|
-
self.logger.info("Infected files: %s", self.infected_files)
|
|
225
|
-
|
|
226
|
-
def reset_all_issues(self):
|
|
227
|
-
"""Reset all issues related to the Maya virus."""
|
|
228
|
-
self._bad_files = []
|
|
229
|
-
self._bad_nodes = []
|
|
230
|
-
self._bad_script_nodes = []
|
|
231
|
-
self._bad_script_jobs = []
|
|
232
|
-
self._infected_files = []
|
|
1
|
+
class AbstractVaccine(object):
|
|
2
|
+
"""Abstract base class for Vaccine classes.
|
|
233
3
|
|
|
4
|
+
Attributes:
|
|
5
|
+
virus_name (str): The name of the virus.
|
|
6
|
+
api (MayaVirusCleaner): The VaccineAPI instance.
|
|
7
|
+
logger (Logger): The logger instance.
|
|
8
|
+
"""
|
|
234
9
|
|
|
235
|
-
class AbstractVaccine(object):
|
|
236
10
|
virus_name = None
|
|
237
11
|
|
|
238
12
|
def __init__(self, api, logger):
|
|
@@ -247,7 +21,17 @@ class AbstractVaccine(object):
|
|
|
247
21
|
self.logger = logger
|
|
248
22
|
|
|
249
23
|
def collect_issues(self):
|
|
24
|
+
"""Collect issues related to the virus.
|
|
25
|
+
|
|
26
|
+
Raises:
|
|
27
|
+
NotImplementedError: This method must be implemented in the derived classes.
|
|
28
|
+
"""
|
|
250
29
|
raise NotImplementedError
|
|
251
30
|
|
|
252
31
|
def report_issue(self, name):
|
|
253
|
-
|
|
32
|
+
"""Report an issue related to the virus.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
name (str): The name of the issue.
|
|
36
|
+
"""
|
|
37
|
+
self.logger.warning(self.api.translator.translate("report_issue", name=name))
|
|
@@ -7,9 +7,10 @@ from maya_umbrella.vaccine import AbstractVaccine
|
|
|
7
7
|
|
|
8
8
|
class Vaccine(AbstractVaccine):
|
|
9
9
|
"""A class for handling the PuTianTongQi virus."""
|
|
10
|
+
virus_name = "PutTianTongQi"
|
|
10
11
|
|
|
11
12
|
def collect_issues(self):
|
|
12
|
-
self.api.
|
|
13
|
+
self.api.add_malicious_files(
|
|
13
14
|
[
|
|
14
15
|
os.path.join(self.api.local_script_path, "fuckVirus.py"),
|
|
15
16
|
os.path.join(self.api.local_script_path, "fuckVirus.pyc"),
|
|
@@ -7,6 +7,7 @@ from maya_umbrella.filesystem import check_virus_by_signature
|
|
|
7
7
|
from maya_umbrella.filesystem import check_virus_file_by_signature
|
|
8
8
|
from maya_umbrella.maya_funs import check_reference_node_exists
|
|
9
9
|
from maya_umbrella.maya_funs import cmds
|
|
10
|
+
from maya_umbrella.maya_funs import get_attr_value
|
|
10
11
|
from maya_umbrella.vaccine import AbstractVaccine
|
|
11
12
|
|
|
12
13
|
|
|
@@ -15,38 +16,37 @@ class Vaccine(AbstractVaccine):
|
|
|
15
16
|
|
|
16
17
|
virus_name = "zei jian kang"
|
|
17
18
|
|
|
18
|
-
def
|
|
19
|
+
def collect_infected_nodes(self):
|
|
19
20
|
"""Collect all bad nodes related to the virus."""
|
|
20
21
|
for script_node in cmds.ls(type="script"):
|
|
21
22
|
if check_reference_node_exists(script_node):
|
|
22
23
|
continue
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
for script_string in [script_before_string, script_after_string]:
|
|
24
|
+
for attr_name in ("before", "after"):
|
|
25
|
+
script_string = get_attr_value(script_node, attr_name)
|
|
26
26
|
if not script_string:
|
|
27
27
|
continue
|
|
28
28
|
if check_virus_by_signature(script_string, JOB_SCRIPTS_VIRUS_SIGNATURES):
|
|
29
29
|
self.report_issue(script_node)
|
|
30
|
-
self.api.
|
|
30
|
+
self.api.add_infected_node(script_node)
|
|
31
31
|
|
|
32
32
|
def collect_issues(self):
|
|
33
33
|
"""Collect all issues related to the virus."""
|
|
34
|
-
self.api.
|
|
34
|
+
self.api.add_malicious_files(
|
|
35
35
|
[
|
|
36
36
|
os.path.join(self.api.local_script_path, "vaccine.py"),
|
|
37
37
|
os.path.join(self.api.local_script_path, "vaccine.pyc"),
|
|
38
38
|
],
|
|
39
39
|
)
|
|
40
|
-
self.
|
|
41
|
-
self.
|
|
40
|
+
self.collect_infected_user_setup_py()
|
|
41
|
+
self.collect_infected_nodes()
|
|
42
42
|
|
|
43
|
-
def
|
|
43
|
+
def collect_infected_user_setup_py(self):
|
|
44
44
|
"""Collect all bad userSetup.py files related to the virus."""
|
|
45
|
-
for
|
|
45
|
+
for user_setup_py in [
|
|
46
46
|
os.path.join(self.api.local_script_path, "userSetup.py"),
|
|
47
47
|
os.path.join(self.api.user_script_path, "userSetup.py"),
|
|
48
48
|
]:
|
|
49
|
-
if os.path.exists(
|
|
50
|
-
if check_virus_file_by_signature(
|
|
51
|
-
self.report_issue(
|
|
52
|
-
self.api.add_infected_file(
|
|
49
|
+
if os.path.exists(user_setup_py):
|
|
50
|
+
if check_virus_file_by_signature(user_setup_py):
|
|
51
|
+
self.report_issue(user_setup_py)
|
|
52
|
+
self.api.add_infected_file(user_setup_py)
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# Import built-in modules
|
|
2
2
|
import glob
|
|
3
|
-
import os
|
|
3
|
+
import os
|
|
4
4
|
|
|
5
5
|
# Import local modules
|
|
6
|
+
from maya_umbrella.constants import JOB_SCRIPTS_VIRUS_SIGNATURES
|
|
7
|
+
from maya_umbrella.filesystem import check_virus_by_signature
|
|
6
8
|
from maya_umbrella.filesystem import check_virus_file_by_signature
|
|
7
9
|
from maya_umbrella.maya_funs import cmds
|
|
10
|
+
from maya_umbrella.maya_funs import get_attr_value
|
|
11
|
+
from maya_umbrella.maya_funs import get_reference_file_by_node
|
|
8
12
|
from maya_umbrella.maya_funs import is_maya_standalone
|
|
9
13
|
from maya_umbrella.vaccine import AbstractVaccine
|
|
10
14
|
|
|
@@ -12,23 +16,27 @@ from maya_umbrella.vaccine import AbstractVaccine
|
|
|
12
16
|
class Vaccine(AbstractVaccine):
|
|
13
17
|
"""A class for handling the virus2024429 virus."""
|
|
14
18
|
|
|
15
|
-
virus_name = "
|
|
19
|
+
virus_name = "Virus2024429"
|
|
16
20
|
|
|
17
|
-
def
|
|
21
|
+
def collect_infected_nodes(self):
|
|
18
22
|
"""Collect all bad nodes related to the virus."""
|
|
19
23
|
for script_node in cmds.ls(type="script"):
|
|
20
|
-
if cmds.referenceQuery(script_node, isNodeReferenced=True):
|
|
21
|
-
continue
|
|
22
|
-
# check uifiguration
|
|
23
|
-
if cmds.objExists("{}.KGMScriptProtector".format(script_node)):
|
|
24
|
-
self.report_issue(script_node)
|
|
25
|
-
self.api.add_bad_node(script_node)
|
|
26
24
|
# check vaccine
|
|
27
25
|
if "_gene" in script_node:
|
|
28
26
|
self.report_issue(script_node)
|
|
29
|
-
self.api.
|
|
27
|
+
self.api.add_infected_node(script_node)
|
|
28
|
+
self.api.add_infected_reference_file(get_reference_file_by_node(script_node))
|
|
29
|
+
if "uifiguration" in script_node:
|
|
30
|
+
for attr_name in ("before", "notes"):
|
|
31
|
+
script_string = get_attr_value(script_node, attr_name)
|
|
32
|
+
if not script_string:
|
|
33
|
+
continue
|
|
34
|
+
if check_virus_by_signature(script_string, JOB_SCRIPTS_VIRUS_SIGNATURES):
|
|
35
|
+
self.report_issue(script_node)
|
|
36
|
+
self.api.add_infected_node(script_node)
|
|
37
|
+
self.api.add_infected_reference_file(get_reference_file_by_node(script_node))
|
|
30
38
|
|
|
31
|
-
def
|
|
39
|
+
def collect_infected_mel_files(self):
|
|
32
40
|
"""Collect all bad MEL files related to the virus."""
|
|
33
41
|
# check usersetup.mel
|
|
34
42
|
# C:/Users/hallong/Documents/maya/scripts/usersetup.mel
|
|
@@ -51,7 +59,7 @@ class Vaccine(AbstractVaccine):
|
|
|
51
59
|
for script_job in cmds.scriptJob(listJobs=True):
|
|
52
60
|
for virus in virus_gene:
|
|
53
61
|
if virus in script_job:
|
|
54
|
-
self.api.
|
|
62
|
+
self.api.add_infected_script_job(script_job)
|
|
55
63
|
|
|
56
64
|
def fix_bad_hik_files(self):
|
|
57
65
|
"""Fix all bad HIK files related to the virus."""
|
|
@@ -63,10 +71,10 @@ class Vaccine(AbstractVaccine):
|
|
|
63
71
|
|
|
64
72
|
def collect_issues(self):
|
|
65
73
|
"""Collect all issues related to the virus."""
|
|
66
|
-
self.api.
|
|
67
|
-
self.
|
|
68
|
-
self.
|
|
74
|
+
self.api.add_malicious_file(os.path.join(os.getenv("APPDATA"), "syssst"))
|
|
75
|
+
self.collect_infected_mel_files()
|
|
76
|
+
self.collect_infected_nodes()
|
|
69
77
|
# This only works for Maya Gui model.
|
|
70
78
|
if not is_maya_standalone():
|
|
71
79
|
self.collect_script_jobs()
|
|
72
|
-
self.api.
|
|
80
|
+
self.api.add_additionally_fix_function(self.fix_bad_hik_files)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: maya_umbrella
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Check and fix maya virus.
|
|
5
5
|
Home-page: https://github.com/loonghao/maya_umbrella
|
|
6
6
|
License: MIT
|
|
@@ -43,18 +43,32 @@ Description-Content-Type: text/markdown
|
|
|
43
43
|
[](https://img.shields.io/badge/maya-2018-green)
|
|
44
44
|
|
|
45
45
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
46
|
-
[](#contributors-)
|
|
47
47
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
48
48
|
|
|
49
|
-
This tool is designed to provide a robust solution for identifying and resolving any potential viruses within Autodesk
|
|
49
|
+
This tool is designed to provide a robust solution for identifying and resolving any potential viruses within Autodesk
|
|
50
|
+
Maya.
|
|
50
51
|
It ensures a secure and seamless user experience by proactively scanning for threats and effectively neutralizing them.
|
|
51
52
|
|
|
52
53
|
It can be provided as an API for seamless integration into your existing pipeline.
|
|
53
54
|
|
|
55
|
+
# 安装
|
|
56
|
+
maya_umbrella是以标准pipy包去发布的,所以我们可以通过pip install去安装
|
|
57
|
+
```shell
|
|
58
|
+
your/maya-root/mayapy -m pip install maya-umbrella
|
|
59
|
+
```
|
|
60
|
+
更新版本
|
|
61
|
+
```shell
|
|
62
|
+
your/maya-root/mayapy -m pip install maya-umbrella --upgrade
|
|
63
|
+
```
|
|
64
|
+
卸载
|
|
65
|
+
```shell
|
|
66
|
+
your/maya-root/mayapy -m pip uninstall maya-umbrella
|
|
67
|
+
```
|
|
54
68
|
|
|
55
69
|
# 开发环境设置
|
|
56
70
|
|
|
57
|
-
Set up the development environment using a virtual environment,
|
|
71
|
+
Set up the development environment using a virtual environment,
|
|
58
72
|
and it is recommended to use Python 3.8 or higher versions.
|
|
59
73
|
|
|
60
74
|
通过虚拟环境去设置开发环境, 推荐python-3.8以上的版本
|
|
@@ -95,6 +109,14 @@ manual_test_in_maya.start()
|
|
|
95
109
|
nox -s ruff_check
|
|
96
110
|
```
|
|
97
111
|
|
|
112
|
+
# 生成安装包
|
|
113
|
+
|
|
114
|
+
执行下面的命令可以在<repo>/.zip下面创建zip,参数 `--version` 当前工具的版本号
|
|
115
|
+
|
|
116
|
+
```shell
|
|
117
|
+
nox -s make-zip -- --version 0.5.0
|
|
118
|
+
```
|
|
119
|
+
|
|
98
120
|
# 环境变量
|
|
99
121
|
|
|
100
122
|
我们可以通过下列环境变量去修改maya_umbrella的一些设置,方便有pipeline的公司可以更好的集成
|
|
@@ -115,6 +137,45 @@ MAYA_UMBRELLA_LOG_NAME
|
|
|
115
137
|
|
|
116
138
|
```shell
|
|
117
139
|
MAYA_UMBRELLA_LOG_LEVEL
|
|
140
|
+
```
|
|
141
|
+
修改杀毒后文件的备份文件夹名称, 默认是`_virus`
|
|
142
|
+
比如:
|
|
143
|
+
你文件路径是 `c:/your/path/file.ma`
|
|
144
|
+
那么备份文件路径是 `c:/your/path/_maya_umbrella/file.ma`
|
|
145
|
+
```shell
|
|
146
|
+
MAYA_UMBRELLA_BACKUP_FOLDER_NAME
|
|
147
|
+
```
|
|
148
|
+
默认的显示语言,包含日志打印输出等,默认是根据你当前maya的界面语言来设置的,当然我们也可以通过下面的环境变量去设置
|
|
149
|
+
```shell
|
|
150
|
+
MAYA_UMBRELLA_LANG
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
忽略保存到备份文件夹,*请注意,如果你不清楚这个会导致的后果请不要轻易修改*,默认批量杀毒后会把源文件自动备份到当前文件的备份文件夹.
|
|
154
|
+
```shell
|
|
155
|
+
MAYA_UMBRELLA_IGNORE_BACKUP
|
|
156
|
+
```
|
|
157
|
+
如果忽略请设置为
|
|
158
|
+
```shell
|
|
159
|
+
SET MAYA_UMBRELLA_IGNORE_BACKUP=true
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
# API
|
|
163
|
+
获取当前场景没有被修复的病毒文件
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from maya_umbrella import MayaVirusDefender
|
|
167
|
+
|
|
168
|
+
api = MayaVirusDefender()
|
|
169
|
+
print(api.get_unfixed_references())
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
批量修复文件
|
|
173
|
+
```python
|
|
174
|
+
from maya_umbrella import MayaVirusScanner
|
|
175
|
+
|
|
176
|
+
api = MayaVirusScanner()
|
|
177
|
+
print(api.scan_files_from_pattern("your/path/*.m[ab]"))
|
|
178
|
+
|
|
118
179
|
```
|
|
119
180
|
|
|
120
181
|
## Contributors ✨
|
|
@@ -131,6 +192,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|
|
131
192
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hotwinter0"><img src="https://avatars.githubusercontent.com/u/106237305?v=4?s=100" width="100px;" alt="hotwinter0"/><br /><sub><b>hotwinter0</b></sub></a><br /><a href="https://github.com/loonghao/maya_umbrella/commits?author=hotwinter0" title="Tests">⚠️</a> <a href="https://github.com/loonghao/maya_umbrella/commits?author=hotwinter0" title="Code">💻</a></td>
|
|
132
193
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lingyunfx"><img src="https://avatars.githubusercontent.com/u/73666629?v=4?s=100" width="100px;" alt="lingyunfx"/><br /><sub><b>lingyunfx</b></sub></a><br /><a href="https://github.com/loonghao/maya_umbrella/commits?author=lingyunfx" title="Tests">⚠️</a></td>
|
|
133
194
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yjjjj"><img src="https://avatars.githubusercontent.com/u/12741735?v=4?s=100" width="100px;" alt="yjjjj"/><br /><sub><b>yjjjj</b></sub></a><br /><a href="https://github.com/loonghao/maya_umbrella/commits?author=yjjjj" title="Tests">⚠️</a> <a href="https://github.com/loonghao/maya_umbrella/commits?author=yjjjj" title="Code">💻</a></td>
|
|
195
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/uncleschen"><img src="https://avatars.githubusercontent.com/u/37014389?v=4?s=100" width="100px;" alt="Unclechen"/><br /><sub><b>Unclechen</b></sub></a><br /><a href="https://github.com/loonghao/maya_umbrella/commits?author=uncleschen" title="Tests">⚠️</a></td>
|
|
134
196
|
</tr>
|
|
135
197
|
</tbody>
|
|
136
198
|
</table>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
maya_umbrella/__init__.py,sha256=uHgbJ-AL3NOfDNB55_7a4_c-OAuP4X8eQ_Yi1udaA0I,401
|
|
2
|
+
maya_umbrella/__version__.py,sha256=cID1jLnC_vj48GgMN6Yb1FA3JsQ95zNmCHmRYE8TFhY,22
|
|
3
|
+
maya_umbrella/cleaner.py,sha256=5EC3w4qRkIsr9AIZneEV8ljhxaOw385Gj2C2KTrzyJg,5044
|
|
4
|
+
maya_umbrella/collector.py,sha256=rAFmvY8Isdle89ezn2-H36hSJd77iBvPBLRPzruCycA,13111
|
|
5
|
+
maya_umbrella/constants.py,sha256=2sl0dL0U82mwu-Msda9B8-USxr89Wu2yu6SYiuaaJZk,539
|
|
6
|
+
maya_umbrella/defender.py,sha256=K5EERl9bwd0IY_ilvnNYXYaQpIe-DUGep-buEb3qLV8,5601
|
|
7
|
+
maya_umbrella/filesystem.py,sha256=CY3MlOXi_fJ8NTITvgotyPiZHyzM4uZQTgMmOYD25T0,8333
|
|
8
|
+
maya_umbrella/hooks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
maya_umbrella/hooks/delete_turtle.py,sha256=OPFRFH1iwonHvETndrP87MZQlJLhxpe564AJE3KyJY8,761
|
|
10
|
+
maya_umbrella/hooks/delete_unknown_plugin_node.py,sha256=xbJvihfjZBhF946ugVqj2IpY_VjOBZt_8KO5omDrJhw,1281
|
|
11
|
+
maya_umbrella/hooks/fix_model_panel.py,sha256=dLuMOz5uQ1nqAboNWMCx-Bi_gHM3FQNTlGxPG5wRYEs,556
|
|
12
|
+
maya_umbrella/hooks/fix_on_model_change_3dc.py,sha256=o4WEQPcHNzaTMXdNnHZWWNCYlHfLxcSFYXR4YW0ZLwk,484
|
|
13
|
+
maya_umbrella/i18n.py,sha256=NCC6isPdchv3yRBS2F4Cguu1bVyi0VoMMcI4YOIxBtU,2683
|
|
14
|
+
maya_umbrella/locales/en_US.json,sha256=LW2gPgO2YJIYR5UfcIBuxW_DS7rf4gkjeVuADqs1V5s,962
|
|
15
|
+
maya_umbrella/locales/zh_CN.json,sha256=UsuRN2yaxxc9LE-7NQkbMqrkjXjNhNegS0QRkQLSTiE,1006
|
|
16
|
+
maya_umbrella/log.py,sha256=IJweFEBTThL6_mW86jAAPKyWNvI79CrMifs5vO3t6ks,1338
|
|
17
|
+
maya_umbrella/maya_funs.py,sha256=WDvREjzLfEsPND0RU-2ErbWgsU6MsILqVBW219p8sZo,3394
|
|
18
|
+
maya_umbrella/scanner.py,sha256=zqo7_Znu1OLI7WrqPBgU1aAxlp19UKVI24s2E-xC6Z8,3710
|
|
19
|
+
maya_umbrella/signatures.py,sha256=RkEXChch7tdqA9Yq6YQ8AMnK2ra6ih0dfnpeZy5FkYs,354
|
|
20
|
+
maya_umbrella/vaccine.py,sha256=aBW6pdT4tD4OMBPZ-d3E4_n16Rylz-2gb7JWzMZVPK0,1022
|
|
21
|
+
maya_umbrella/vaccines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
|
+
maya_umbrella/vaccines/vaccine1.py,sha256=WLo1uJElTLSjVCf5CBtRNU4HKs63my5mkHiGqTfnNEE,489
|
|
23
|
+
maya_umbrella/vaccines/vaccine2.py,sha256=yvHpnrQ6Jts9_zCy8WRJcbxz0CVSRAPkn2vF552atQs,2123
|
|
24
|
+
maya_umbrella/vaccines/vaccine3.py,sha256=d89Ocj1AmsZt9YJjggjDJqAWXcckGLMl-6u8jXeAPjg,3493
|
|
25
|
+
maya_umbrella-0.6.0.dist-info/LICENSE,sha256=tJf0Pz8q_65AjEkm3872K1cl4jGil28vJO5Ko_LhUqc,1060
|
|
26
|
+
maya_umbrella-0.6.0.dist-info/METADATA,sha256=JYAKRBCSJIq-vbrfRfehI97VuZPzAyyTo9drpkgofI0,9178
|
|
27
|
+
maya_umbrella-0.6.0.dist-info/WHEEL,sha256=IrRNNNJ-uuL1ggO5qMvT1GGhQVdQU54d6ZpYqEZfEWo,92
|
|
28
|
+
maya_umbrella-0.6.0.dist-info/RECORD,,
|
maya_umbrella/core.py
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# Import built-in modules
|
|
2
|
-
import logging
|
|
3
|
-
|
|
4
|
-
# Import local modules
|
|
5
|
-
from maya_umbrella.filesystem import get_hooks
|
|
6
|
-
from maya_umbrella.filesystem import get_vaccines
|
|
7
|
-
from maya_umbrella.filesystem import load_hook
|
|
8
|
-
from maya_umbrella.log import setup_logger
|
|
9
|
-
from maya_umbrella.maya_funs import is_maya_standalone
|
|
10
|
-
from maya_umbrella.maya_funs import om
|
|
11
|
-
from maya_umbrella.vaccine import MayaVirusCleaner
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class MayaVirusDefender(object):
|
|
15
|
-
callback_ids = []
|
|
16
|
-
remove_callbacks = []
|
|
17
|
-
_bad_files = []
|
|
18
|
-
_vaccines = []
|
|
19
|
-
callback_maps = {
|
|
20
|
-
"after_open": om.MSceneMessage.kAfterOpen,
|
|
21
|
-
"maya_initialized": om.MSceneMessage.kMayaInitialized,
|
|
22
|
-
"after_import": om.MSceneMessage.kAfterImport,
|
|
23
|
-
"after_import_reference": om.MSceneMessage.kAfterImportReference,
|
|
24
|
-
"after_load_reference": om.MSceneMessage.kAfterLoadReference,
|
|
25
|
-
"before_save": om.MSceneMessage.kBeforeSave,
|
|
26
|
-
"before_import": om.MSceneMessage.kBeforeImport,
|
|
27
|
-
"before_load_reference": om.MSceneMessage.kBeforeLoadReference,
|
|
28
|
-
"before_import_reference": om.MSceneMessage.kBeforeImportReference,
|
|
29
|
-
"maya_exiting": om.MSceneMessage.kMayaExiting,
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
def __init__(self, auto_fix=True):
|
|
33
|
-
"""Initialize the MayaVirusDefender.
|
|
34
|
-
|
|
35
|
-
Args:
|
|
36
|
-
auto_fix (bool): Whether to automatically fix issues.
|
|
37
|
-
"""
|
|
38
|
-
logger = logging.getLogger(__name__)
|
|
39
|
-
self.auto_fix = auto_fix
|
|
40
|
-
self.logger = setup_logger(logger)
|
|
41
|
-
self.virus_cleaner = MayaVirusCleaner(self.logger)
|
|
42
|
-
self.load_vaccines()
|
|
43
|
-
|
|
44
|
-
def load_vaccines(self):
|
|
45
|
-
"""Load all vaccines."""
|
|
46
|
-
for vaccine in get_vaccines():
|
|
47
|
-
vaccine_class = load_hook(vaccine).Vaccine
|
|
48
|
-
try:
|
|
49
|
-
self._vaccines.append(vaccine_class(api=self.virus_cleaner, logger=self.logger))
|
|
50
|
-
except Exception as e:
|
|
51
|
-
self.logger.error("Error loading vaccine: %s", e)
|
|
52
|
-
|
|
53
|
-
@property
|
|
54
|
-
def vaccines(self):
|
|
55
|
-
"""Get all loaded vaccines.
|
|
56
|
-
|
|
57
|
-
Returns:
|
|
58
|
-
list: A list of loaded vaccines.
|
|
59
|
-
"""
|
|
60
|
-
return self._vaccines
|
|
61
|
-
|
|
62
|
-
def run_hooks(self):
|
|
63
|
-
"""Run all hooks, only works in non-batch mode."""
|
|
64
|
-
if not is_maya_standalone():
|
|
65
|
-
for hook_file in get_hooks():
|
|
66
|
-
self.logger.debug("run_hook: %s", hook_file)
|
|
67
|
-
try:
|
|
68
|
-
load_hook(hook_file).hook(virus_cleaner=self.virus_cleaner)
|
|
69
|
-
except Exception as e:
|
|
70
|
-
self.logger.error("Error running hook: %s", e)
|
|
71
|
-
|
|
72
|
-
def collect(self):
|
|
73
|
-
"""Collect all issues related to the Maya virus."""
|
|
74
|
-
for vaccine in self.vaccines:
|
|
75
|
-
vaccine.collect_issues()
|
|
76
|
-
|
|
77
|
-
def reset(self):
|
|
78
|
-
"""Reset internal buffer."""
|
|
79
|
-
self.virus_cleaner.reset_all_issues()
|
|
80
|
-
|
|
81
|
-
def fix(self):
|
|
82
|
-
"""Fix all issues related to the Maya virus."""
|
|
83
|
-
self.virus_cleaner.fix_all_issues()
|
|
84
|
-
|
|
85
|
-
def report(self):
|
|
86
|
-
"""Report all issues related to the Maya virus."""
|
|
87
|
-
self.reset()
|
|
88
|
-
self.collect()
|
|
89
|
-
self.virus_cleaner.report_all_issues()
|
|
90
|
-
|
|
91
|
-
def setup(self):
|
|
92
|
-
"""Set up the MayaVirusDefender."""
|
|
93
|
-
self.virus_cleaner.setup_default_callbacks()
|
|
94
|
-
for name, callbacks in self.virus_cleaner.registered_callbacks.items():
|
|
95
|
-
maya_callback = self.callback_maps[name]
|
|
96
|
-
self.logger.debug("%s setup.", name)
|
|
97
|
-
for func in callbacks:
|
|
98
|
-
self.callback_ids.append(om.MSceneMessage.addCallback(maya_callback, func))
|
|
99
|
-
for name, callbacks in self.callback_maps.items():
|
|
100
|
-
self.logger.debug("setup callback %s.", name)
|
|
101
|
-
self.callback_ids.append(om.MSceneMessage.addCallback(callbacks, self._callback))
|
|
102
|
-
|
|
103
|
-
def _callback(self, *args, **kwargs):
|
|
104
|
-
"""Callback function for MayaVirusDefender.
|
|
105
|
-
|
|
106
|
-
Args:
|
|
107
|
-
*args: Variable length argument list.
|
|
108
|
-
**kwargs: Arbitrary keyword arguments.
|
|
109
|
-
"""
|
|
110
|
-
if self.auto_fix:
|
|
111
|
-
self.reset()
|
|
112
|
-
self.collect()
|
|
113
|
-
self.fix()
|
|
114
|
-
self.run_hooks()
|
|
115
|
-
else:
|
|
116
|
-
self.report()
|
|
117
|
-
|
|
118
|
-
def start(self):
|
|
119
|
-
"""Start the MayaVirusDefender."""
|
|
120
|
-
self._callback()
|