1
+ # Blender FLIP Fluids Add-on
2
+ # Copyright (C) 2020 Ryan L. Guy
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ import bpy , os , pathlib
18
+
19
+
20
+ __EXTENSION_WHITELIST = [
21
+ ".backup" ,
22
+ ".bbox" ,
23
+ ".bobj" ,
24
+ ".data" ,
25
+ ".ffd" ,
26
+ ".fpd" ,
27
+ ".info" ,
28
+ ".md" ,
29
+ ".png" ,
30
+ ".preset" ,
31
+ ".sim" ,
32
+ ".sqlite3" ,
33
+ ".state" ,
34
+ ".txt" ,
35
+ ".wwp"
36
+ ]
37
+
38
+
39
+ class FilesystemProtectionError (Exception ):
40
+ def __init__ (self , value ):
41
+ self .value = value
42
+ def __str__ (self ):
43
+ return repr (self .value )
44
+
45
+
46
+ def get_extension_whitelist ():
47
+ global __EXTENSION_WHITELIST
48
+ return __EXTENSION_WHITELIST
49
+
50
+
51
+ def get_directory_whitelist ():
52
+ whitelist = []
53
+ dprops = bpy .context .scene .flip_fluid .get_domain_properties ()
54
+ if dprops is not None :
55
+ whitelist .append (dprops .cache .get_cache_abspath ())
56
+
57
+ this_filepath = os .path .realpath (__file__ )
58
+ addon_filepath = os .path .dirname (os .path .dirname (this_filepath ))
59
+ whitelist .append (addon_filepath )
60
+
61
+ return whitelist
62
+
63
+
64
+ def path_is_parent (parent_path , child_path ):
65
+ parent_path = os .path .abspath (parent_path )
66
+ child_path = os .path .abspath (child_path )
67
+ return os .path .commonpath ([parent_path ]) == os .path .commonpath ([parent_path , child_path ])
68
+
69
+
70
+ def check_extensions_valid (extensions ):
71
+ extension_whitelist = get_extension_whitelist ()
72
+ bad_extensions = []
73
+ for ext in extensions :
74
+ if ext not in extension_whitelist :
75
+ bad_extensions .append (ext )
76
+
77
+ if bad_extensions :
78
+ error_msg = "Extension not in whitelist: "
79
+ for ext in bad_extensions :
80
+ error_msg += "<" + ext + "> "
81
+ error_msg += "***Please contact the developers with this error message***"
82
+ raise FilesystemProtectionError (error_msg )
83
+
84
+
85
+ def check_directory_valid (base_directory ):
86
+ directory_whitelist = get_directory_whitelist ()
87
+ is_safe_sub_directory = False
88
+ for d in directory_whitelist :
89
+ if path_is_parent (d , base_directory ):
90
+ is_safe_sub_directory = True
91
+ break
92
+
93
+ if not is_safe_sub_directory :
94
+ error_msg = "Directory is not in whitelist: <" + base_directory + "> Whitelist: "
95
+ for d in directory_whitelist :
96
+ error_msg += "<" + d + "> "
97
+ error_msg += "***Please contact the developers with this error message***"
98
+ raise FilesystemProtectionError (error_msg )
99
+
100
+
101
+ def delete_files_in_directory (base_directory , extensions , remove_directory = False ):
102
+ check_extensions_valid (extensions )
103
+ check_directory_valid (base_directory )
104
+
105
+ if not os .path .isdir (base_directory ):
106
+ return
107
+
108
+ file_list = [f for f in os .listdir (base_directory ) if os .path .isfile (os .path .join (base_directory , f ))]
109
+ valid_filepaths = []
110
+ for f in file_list :
111
+ if pathlib .Path (f ).suffix in extensions :
112
+ valid_filepaths .append (os .path .join (base_directory , f ))
113
+
114
+ for f in valid_filepaths :
115
+ os .remove (f )
116
+
117
+ if remove_directory and not os .listdir (base_directory ):
118
+ os .rmdir (base_directory )
119
+
120
+
121
+ def delete_file (filepath ):
122
+ if not os .path .isfile (filepath ):
123
+ return
124
+
125
+ extension = pathlib .Path (filepath ).suffix
126
+ check_extensions_valid ([extension ])
127
+ check_directory_valid (filepath )
128
+ os .remove (filepath )
129
+
130
+
131
+ def clear_cache_directory (cache_directory , clear_export = False , clear_logs = False , remove_directory = False ):
132
+ stats_filepath = os .path .join (cache_directory , "flipstats.data" )
133
+ delete_file (stats_filepath )
134
+
135
+ bakefiles_dir = os .path .join (cache_directory , "bakefiles" )
136
+ extensions = [".bbox" , ".bobj" , ".wwp" , ".fpd" , ".ffd" ]
137
+ delete_files_in_directory (bakefiles_dir , extensions , remove_directory = True )
138
+
139
+ temp_dir = os .path .join (cache_directory , "temp" )
140
+ extensions = [".data" ]
141
+ delete_files_in_directory (temp_dir , extensions , remove_directory = True )
142
+
143
+ savestates_dir = os .path .join (cache_directory , "savestates" )
144
+ if os .path .isdir (savestates_dir ):
145
+ extensions = [".data" , ".state" ]
146
+ savestate_subdirs = [d for d in os .listdir (savestates_dir ) if os .path .isdir (os .path .join (savestates_dir , d ))]
147
+ for subd in savestate_subdirs :
148
+ if subd .startswith ("autosave" ):
149
+ dirpath = os .path .join (savestates_dir , subd )
150
+ delete_files_in_directory (dirpath , extensions , remove_directory = True )
151
+ delete_files_in_directory (savestates_dir , [], remove_directory = True )
152
+
153
+ if clear_export :
154
+ export_dir = os .path .join (cache_directory , "export" )
155
+ if os .path .isdir (export_dir ):
156
+ extensions = [".sqlite3" , ".sim" ]
157
+ delete_files_in_directory (export_dir , extensions , remove_directory = True )
158
+
159
+ if clear_logs :
160
+ logs_dir = os .path .join (cache_directory , "logs" )
161
+ if os .path .isdir (logs_dir ):
162
+ extensions = [".txt" ]
163
+ delete_files_in_directory (logs_dir , extensions , remove_directory = True )
164
+
165
+ if remove_directory and not os .listdir (cache_directory ):
166
+ os .rmdir (cache_directory )
0 commit comments