def get_commands(self): for path in paths: if not isinstance(path, (str)): raise RuntimeError('expected path as string but got %s' % str(path)) if not os.path.isabs(path): path = os.path.abspath(path) if os.path.isdir(path): for child in children_in_directory(path, True): yield Command.Shred(child) yield Command.Shred(path)
def get_commands(self): for path in paths: if not isinstance(path, (str, unicode)): raise RuntimeError( 'expected path as string but got %s' % str(path)) if not os.path.isabs(path): path = os.path.abspath(path) if os.path.isdir(path): for child in children_in_directory(path, True): yield Command.Shred(child) yield Command.Shred(path) else: yield Command.Shred(path)
def get_commands(self): for path in paths: # create_simple_cleaner함수를 호출할 때 쓴 경로의 파일 반복 if not isinstance(path, (str, unicode)): # path가 이 클래스의 할당 및 호환이 가능하지 않으면 raise RuntimeError( # 런타임 에러 발생 'expected path as string but got %s' % str(path)) if not os.path.isabs(path): # 만약 path가 절대경로가 아니면 path = os.path.abspath(path) # path를 절대경로로 바꾼다. if os.path.isdir(path): # 만약 path가 디렉토리이면 for child in children_in_directory(path, True): yield Command.Shred(child) # path의 파일 및 하위 디렉토리를 잘라낸다. yield Command.Shred(path) # path를 잘라낸다 -> 디렉토리와 디렉토리의 내용까지 다 잘라내는 코드 else: yield Command.Shred(path) # path가 디렉토리가 아니면 path를 잘라냄 -> 파일일 경우 파일만 잘라내는 코드
def get_commands(self, option_id): # paths for which to run expand_glob_join egj = [] # expand_glob_join을 사용하기 위한 경로를 저장하는 용도 if 'recent_documents' == option_id: # option_id가 recent_documents(최근 문서) 이면 egj.append( "user/registry/data/org/openoffice/Office/Histories.xcu") # egj에 경로를 추가 egj.append( "user/registry/cache/org.openoffice.Office.Histories.dat") # egj에 경로를 추가 if 'recent_documents' == option_id and not 'cache' == option_id: # option_id가 recent_documents 이고 cache가 아니면 egj.append("user/registry/cache/org.openoffice.Office.Common.dat") # 다음 경로를 추가 for egj_ in egj: # egj에 들어있는 경로를 반복 for prefix in self.prefixes: # prefixes에 저장된 경로를 반복 for path in FileUtilities.expand_glob_join(prefix, egj_): # prefix와 egj의 경로를 os형식에 맞게 연결하고 # prefix와 egj의 경로에 환경변수가 있으면 확장한다음 # 경로의 "~"을 사용자 디렉토리의 절대경로로 대체한다. # 대체한 경로에 대응되는 모든 파일 및 디렉터리의 리스트를 이터레이터로 반환한 것을 반복 if 'nt' == os.name: # os 이름 확인 path = os.path.normpath(path) # path의 경로를 정규화 ( 현재 디렉터리"."나 상위 디렉터리".."같은 구분자를 최대한 삭제) if os.path.lexists(path): # 경로의 파일이 존재하는지 확인 yield Command.Delete(path) # 존재하면 삭제 if 'cache' == option_id: # option_id가 캐시일때 dirs = [] for prefix in self.prefixes: # prefixes에 저장된 경로 반복 dirs += FileUtilities.expand_glob_join( # prefixies에 저장된 경로와 user/registry/cache/ 를 os형식에 맞게 연결하고 prefix, "user/registry/cache/") # 확장한다음 dirs에 추가 for dirname in dirs: # dir에 저장된 경로 반복 if 'nt' == os.name: # os가 윈도우NT면 dirname = os.path.normpath(dirname) # 경로를 정규화해서 dirname에 저장 for filename in children_in_directory(dirname, False): yield Command.Delete(filename) # filename을 삭제 if 'recent_documents' == option_id: # option_id가 최근 문서일 경우 for prefix in self.prefixes: for path in FileUtilities.expand_glob_join(prefix, "user/registry/data/org/openoffice/Office/Common.xcu"): # prefixies에 저장된 경로와 user/registry/data/org/openoffice/Office/Common.xcu를 연결하고 확장한다음 반복 if os.path.lexists(path): # path가 존재하는지 확인 yield Command.Function(path, Special.delete_ooo_history, _('Delete the usage history')) # ~/.openoffice.org/3/user/registrymodifications.xcu # Apache OpenOffice.org 3.4.1 from openoffice.org on Ubuntu 13.04 # %AppData%\OpenOffice.org\3\user\registrymodifications.xcu # Apache OpenOffice.org 3.4.1 from openoffice.org on Windows XP for path in FileUtilities.expand_glob_join(prefix, "user/registrymodifications.xcu"): if os.path.lexists(path): yield Command.Function(path, Special.delete_office_registrymodifications, _('Delete the usage history'))
def get_commands(self, option_id): # paths for which to run expand_glob_join egj = [] if 'recent_documents' == option_id: egj.append( "user/registry/data/org/openoffice/Office/Histories.xcu") egj.append( "user/registry/cache/org.openoffice.Office.Histories.dat") if 'recent_documents' == option_id and not 'cache' == option_id: egj.append("user/registry/cache/org.openoffice.Office.Common.dat") for egj_ in egj: for prefix in self.prefixes: for path in FileUtilities.expand_glob_join(prefix, egj_): if 'nt' == os.name: path = os.path.normpath(path) if os.path.lexists(path): yield Command.Delete(path) if 'cache' == option_id: dirs = [] for prefix in self.prefixes: dirs += FileUtilities.expand_glob_join(prefix, "user/registry/cache/") for dirname in dirs: if 'nt' == os.name: dirname = os.path.normpath(dirname) for filename in children_in_directory(dirname, False): yield Command.Delete(filename) if 'recent_documents' == option_id: for prefix in self.prefixes: for path in FileUtilities.expand_glob_join( prefix, "user/registry/data/org/openoffice/Office/Common.xcu"): if os.path.lexists(path): yield Command.Function(path, Special.delete_ooo_history, _('Delete the usage history')) # ~/.openoffice.org/3/user/registrymodifications.xcu # Apache OpenOffice.org 3.4.1 from openoffice.org on Ubuntu 13.04 # %AppData%\OpenOffice.org\3\user\registrymodifications.xcu # Apache OpenOffice.org 3.4.1 from openoffice.org on Windows XP for path in FileUtilities.expand_glob_join( prefix, "user/registrymodifications.xcu"): if os.path.lexists(path): yield Command.Function( path, Special.delete_office_registrymodifications, _('Delete the usage history'))
def get_commands(self, option_id): # paths for which to run expand_glob_join egj = [] if 'recent_documents' == option_id: egj.append( "user/registry/data/org/openoffice/Office/Histories.xcu") egj.append( "user/registry/cache/org.openoffice.Office.Histories.dat") if 'recent_documents' == option_id and not 'cache' == option_id: egj.append("user/registry/cache/org.openoffice.Office.Common.dat") for egj_ in egj: for prefix in self.prefixes: for path in FileUtilities.expand_glob_join(prefix, egj_): if 'nt' == os.name: path = os.path.normpath(path) if os.path.lexists(path): yield Command.Delete(path) if 'cache' == option_id: dirs = [] for prefix in self.prefixes: dirs += FileUtilities.expand_glob_join( prefix, "user/registry/cache/") for dirname in dirs: if 'nt' == os.name: dirname = os.path.normpath(dirname) for filename in children_in_directory(dirname, False): yield Command.Delete(filename) if 'recent_documents' == option_id: for prefix in self.prefixes: for path in FileUtilities.expand_glob_join(prefix, "user/registry/data/org/openoffice/Office/Common.xcu"): if os.path.lexists(path): yield Command.Function(path, Special.delete_ooo_history, _('Delete the usage history')) # ~/.openoffice.org/3/user/registrymodifications.xcu # Apache OpenOffice.org 3.4.1 from openoffice.org on Ubuntu 13.04 # %AppData%\OpenOffice.org\3\user\registrymodifications.xcu # Apache OpenOffice.org 3.4.1 from openoffice.org on Windows XP for path in FileUtilities.expand_glob_join(prefix, "user/registrymodifications.xcu"): if os.path.lexists(path): yield Command.Function(path, Special.delete_office_registrymodifications, _('Delete the usage history'))
def get_commands(self, option_id): # cache if 'posix' == os.name and 'cache' == option_id: dirname = expanduser("~/.cache/") for filename in children_in_directory(dirname, True): if not self.whitelisted(filename): yield Command.Delete(filename) # custom if 'custom' == option_id: for (c_type, c_path) in options.get_custom_paths(): if 'file' == c_type: yield Command.Delete(c_path) elif 'folder' == c_type: yield Command.Delete(c_path) for path in children_in_directory(c_path, True): yield Command.Delete(path) else: raise RuntimeError('custom folder has invalid type %s' % c_type) # menu menu_dirs = [ '~/.local/share/applications', '~/.config/autostart', '~/.gnome/apps/', '~/.gnome2/panel2.d/default/launchers', '~/.gnome2/vfolders/applications/', '~/.kde/share/apps/RecentDocuments/', '~/.kde/share/mimelnk', '~/.kde/share/mimelnk/application/ram.desktop', '~/.kde2/share/mimelnk/application/', '~/.kde2/share/applnk' ] if 'posix' == os.name and 'desktop_entry' == option_id: for dirname in menu_dirs: for filename in [ fn for fn in children_in_directory(dirname, False) if fn.endswith('.desktop') ]: if Unix.is_broken_xdg_desktop(filename): yield Command.Delete(filename) # unwanted locales if 'posix' == os.name and 'localizations' == option_id: for path in Unix.locales.localization_paths( locales_to_keep=options.get_languages()): if os.path.isdir(path): for f in FileUtilities.children_in_directory(path, True): yield Command.Delete(f) yield Command.Delete(path) # Windows logs if 'nt' == os.name and 'logs' == option_id: paths = ( '$ALLUSERSPROFILE\\Application Data\\Microsoft\\Dr Watson\\*.log', '$ALLUSERSPROFILE\\Application Data\\Microsoft\\Dr Watson\\user.dmp', '$LocalAppData\\Microsoft\\Windows\\WER\\ReportArchive\\*\\*', '$LocalAppData\\Microsoft\\Windows\WER\\ReportQueue\\*\\*', '$programdata\\Microsoft\\Windows\\WER\\ReportArchive\\*\\*', '$programdata\\Microsoft\\Windows\\WER\\ReportQueue\\*\\*', '$localappdata\\Microsoft\\Internet Explorer\\brndlog.bak', '$localappdata\\Microsoft\\Internet Explorer\\brndlog.txt', '$windir\\*.log', '$windir\\imsins.BAK', '$windir\\OEWABLog.txt', '$windir\\SchedLgU.txt', '$windir\\ntbtlog.txt', '$windir\\setuplog.txt', '$windir\\REGLOCS.OLD', '$windir\\Debug\\*.log', '$windir\\Debug\\Setup\\UpdSh.log', '$windir\\Debug\\UserMode\\*.log', '$windir\\Debug\\UserMode\\ChkAcc.bak', '$windir\\Debug\\UserMode\\userenv.bak', '$windir\\Microsoft.NET\Framework\*\*.log', '$windir\\pchealth\\helpctr\\Logs\\hcupdate.log', '$windir\\security\\logs\\*.log', '$windir\\security\\logs\\*.old', '$windir\\SoftwareDistribution\\*.log', '$windir\\SoftwareDistribution\\DataStore\\Logs\\*', '$windir\\system32\\TZLog.log', '$windir\\system32\\config\\systemprofile\\Application Data\\Microsoft\\Internet Explorer\\brndlog.bak', '$windir\\system32\\config\\systemprofile\\Application Data\\Microsoft\\Internet Explorer\\brndlog.txt', '$windir\\system32\\LogFiles\\AIT\\AitEventLog.etl.???', '$windir\\system32\\LogFiles\\Firewall\\pfirewall.log*', '$windir\\system32\\LogFiles\\Scm\\SCM.EVM*', '$windir\\system32\\LogFiles\\WMI\\Terminal*.etl', '$windir\\system32\\LogFiles\\WMI\\RTBackup\EtwRT.*etl', '$windir\\system32\\wbem\\Logs\\*.lo_', '$windir\\system32\\wbem\\Logs\\*.log', ) for path in paths: expanded = expandvars(path) for globbed in glob.iglob(expanded): yield Command.Delete(globbed) # memory if sys.platform.startswith('linux') and 'memory' == option_id: yield Command.Function(None, Memory.wipe_memory, _('Memory')) # memory dump # how to manually create this file # http://www.pctools.com/guides/registry/detail/856/ if 'nt' == os.name and 'memory_dump' == option_id: fname = expandvars('$windir\\memory.dmp') if os.path.exists(fname): yield Command.Delete(fname) for fname in glob.iglob(expandvars('$windir\\Minidump\\*.dmp')): yield Command.Delete(fname) # most recently used documents list if 'posix' == os.name and 'recent_documents' == option_id: ru_fn = expanduser("~/.recently-used") if os.path.lexists(ru_fn): yield Command.Delete(ru_fn) # GNOME 2.26 (as seen on Ubuntu 9.04) will retain the list # in memory if it is simply deleted, so it must be shredded # (or at least truncated). # # GNOME 2.28.1 (Ubuntu 9.10) and 2.30 (10.04) do not re-read # the file after truncation, but do re-read it after # shredding. # # https://bugzilla.gnome.org/show_bug.cgi?id=591404 def gtk_purge_items(): """Purge GTK items""" gtk.RecentManager().purge_items() yield 0 for pathname in [ "~/.recently-used.xbel", "~/.local/share/recently-used.xbel" ]: pathname = expanduser(pathname) if os.path.lexists(pathname): yield Command.Shred(pathname) if HAVE_GTK: # Use the Function to skip when in preview mode yield Command.Function(None, gtk_purge_items, _('Recent documents list')) if 'posix' == os.name and 'rotated_logs' == option_id: for path in Unix.rotated_logs(): yield Command.Delete(path) # temporary files if 'posix' == os.name and 'tmp' == option_id: dirnames = ['/tmp', '/var/tmp'] for dirname in dirnames: for path in children_in_directory(dirname, True): is_open = FileUtilities.openfiles.is_open(path) ok = not is_open and os.path.isfile(path) and \ not os.path.islink(path) and \ FileUtilities.ego_owner(path) and \ not self.whitelisted(path) if ok: yield Command.Delete(path) # temporary files if 'nt' == os.name and 'tmp' == option_id: dirname1 = expandvars("$USERPROFILE\\Local Settings\\Temp\\") dirname2 = expandvars(r'%temp%') dirname3 = expandvars("%windir%\\temp\\") dirnames = [] if Windows.get_windows_version() >= 6.0: # Windows Vista or later dirnames.append(dirname2) else: # Windows XP dirnames.append(dirname1) dirnames.append(dirname3) # whitelist the folder %TEMP%\Low but not its contents # https://bugs.launchpad.net/bleachbit/+bug/1421726 for dirname in dirnames: low = os.path.join(dirname, 'low').lower() for filename in children_in_directory(dirname, True): if not low == filename.lower(): yield Command.Delete(filename) # trash if 'posix' == os.name and 'trash' == option_id: dirname = expanduser("~/.Trash") for filename in children_in_directory(dirname, False): yield Command.Delete(filename) # fixme http://www.ramendik.ru/docs/trashspec.html # http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html # ~/.local/share/Trash # * GNOME 2.22, Fedora 9 # * KDE 4.1.3, Ubuntu 8.10 dirname = expanduser("~/.local/share/Trash/files") for filename in children_in_directory(dirname, True): yield Command.Delete(filename) dirname = expanduser("~/.local/share/Trash/info") for filename in children_in_directory(dirname, True): yield Command.Delete(filename) dirname = expanduser("~/.local/share/Trash/expunged") # [email protected] tells me that the trash # backend puts files in here temporary, but in some situations # the files are stuck. for filename in children_in_directory(dirname, True): yield Command.Delete(filename) # clipboard if HAVE_GTK and 'clipboard' == option_id: def clear_clipboard(): gtk.gdk.threads_enter() clipboard = gtk.clipboard_get() clipboard.set_text("") gtk.gdk.threads_leave() return 0 yield Command.Function(None, clear_clipboard, _('Clipboard')) # overwrite free space shred_drives = options.get_list('shred_drives') if 'free_disk_space' == option_id and shred_drives: for pathname in shred_drives: # TRANSLATORS: 'Free' means 'unallocated.' # %s expands to a path such as C:\ or /tmp/ display = _("Overwrite free disk space %s") % pathname def wipe_path_func(): for ret in FileUtilities.wipe_path(pathname, idle=True): # Yield control to GTK idle because this process # is very slow. Also display progress. yield ret yield 0 yield Command.Function(None, wipe_path_func, display) # MUICache if 'nt' == os.name and 'muicache' == option_id: keys = ( 'HKCU\\Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache', 'HKCU\\Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache' ) for key in keys: yield Command.Winreg(key, None) # prefetch if 'nt' == os.name and 'prefetch' == option_id: for path in glob.iglob(expandvars('$windir\\Prefetch\\*.pf')): yield Command.Delete(path) # recycle bin if 'nt' == os.name and 'recycle_bin' == option_id: # This method allows shredding recycled_any = False for path in Windows.get_recycle_bin(): recycled_any = True yield Command.Delete(path) # If there were any files deleted, Windows XP will show the # wrong icon for the recycle bin indicating it is not empty. # The icon will be incorrect until logging in to Windows again # or until it is emptied using the Windows API call for emptying # the recycle bin. # Windows 10 refreshes the recycle bin icon when the user # opens the recycle bin folder. # This is a hack to refresh the icon. def empty_recycle_bin_func(): import tempfile tmpdir = tempfile.mkdtemp() Windows.move_to_recycle_bin(tmpdir) try: Windows.empty_recycle_bin(None, True) except: logging.getLogger(__name__).info( 'error in empty_recycle_bin()', exc_info=True) yield 0 # Using the Function Command prevents emptying the recycle bin # when in preview mode. if recycled_any: yield Command.Function(None, empty_recycle_bin_func, _('Empty the recycle bin')) # Windows Updates if 'nt' == os.name and 'updates' == option_id: for wu in Windows.delete_updates(): yield wu
def get_commands(self, option_id): files = [] # backup files if 'backup' == option_id: bookmark_bu_dir = os.path.join(self.profile_dir, 'bookmarkbackups') files += FileUtilities.expand_glob_join(bookmark_bu_dir, "*.json") files += FileUtilities.expand_glob_join( bookmark_bu_dir, "*.jsonlz4") # browser cache cache_base = None if 'posix' == os.name: cache_base = self.profile_dir elif 'nt' == os.name: cache_base = "$localappdata\\Mozilla\\Firefox\\Profiles\\*.default*" if 'cache' == option_id: dirs = FileUtilities.expand_glob_join(cache_base, "Cache*") dirs += FileUtilities.expand_glob_join(cache_base, "OfflineCache") if 'nt' == os.name: dirs += FileUtilities.expand_glob_join( cache_base, "jumpListCache") # Windows 8 if 'posix' == os.name: # This path is whitelisted under the System - Cache cleaner, # so it can be cleaned here. dirs += [expanduser('~/.cache/mozilla')] for dirname in dirs: for filename in children_in_directory(dirname, False): yield Command.Delete(filename) # Necko Predictive Network Actions # https://wiki.mozilla.org/Privacy/Reviews/Necko files += FileUtilities.expand_glob_join( self.profile_dir, "netpredictions.sqlite") # cookies if 'cookies' == option_id: files += FileUtilities.expand_glob_join( self.profile_dir, "cookies.txt") files += FileUtilities.expand_glob_join( self.profile_dir, "cookies.sqlite") # crash reports if 'posix' == os.name: crashdir = expanduser("~/.mozilla/firefox/Crash Reports") if 'nt' == os.name: crashdir = expandvars( "$USERPROFILE\\Application Data\\Mozilla\\Firefox\\Crash Reports") if 'crash_reports' == option_id: for filename in children_in_directory(crashdir, False): files += [filename] files += FileUtilities.expand_glob_join( self.profile_dir, "minidumps/*.dmp") # DOM storage if 'dom' == option_id: files += FileUtilities.expand_glob_join( self.profile_dir, "webappsstore.sqlite") # download history if 'download_history' == option_id: # Firefox version 1 files += FileUtilities.expand_glob_join( self.profile_dir, "downloads.rdf") # Firefox version 3 files += FileUtilities.expand_glob_join( self.profile_dir, "downloads.sqlite") # forms if 'forms' == option_id: files += FileUtilities.expand_glob_join( self.profile_dir, "formhistory.dat") files += FileUtilities.expand_glob_join( self.profile_dir, "formhistory.sqlite") # passwords if 'passwords' == option_id: # http://kb.mozillazine.org/Password_Manager files += FileUtilities.expand_glob_join( self.profile_dir, "signons.txt") files += FileUtilities.expand_glob_join( self.profile_dir, "signons[2-3].txt") files += FileUtilities.expand_glob_join( self.profile_dir, "signons.sqlite") files += FileUtilities.expand_glob_join( self.profile_dir, "logins.json") # session restore if 'session_restore' == option_id: # Names include sessionstore.js, sessionstore.bak, # sessionstore.bak-20140715214327, sessionstore-1.js files += FileUtilities.expand_glob_join( self.profile_dir, "sessionstore*.js") files += FileUtilities.expand_glob_join( self.profile_dir, "sessionstore.bak*") ss_bu_dir = os.path.join(self.profile_dir, 'sessionstore-backups') files += FileUtilities.expand_glob_join( ss_bu_dir, 'previous.js') files += FileUtilities.expand_glob_join( ss_bu_dir, 'upgrade.js-20*') files += FileUtilities.expand_glob_join( ss_bu_dir, 'recovery.js') files += FileUtilities.expand_glob_join( ss_bu_dir, 'recovery.bak') # site-specific preferences if 'site_preferences' == option_id: files += FileUtilities.expand_glob_join( self.profile_dir, "content-prefs.sqlite") # URL history if 'url_history' == option_id: # Firefox version 1 files += FileUtilities.expand_glob_join( self.profile_dir, "history.dat") # Firefox 21 on Windows if 'nt' == os.name: files += FileUtilities.expand_glob_join( cache_base, "thumbnails/*.png") # see also function other_cleanup() # finish for filename in files: yield Command.Delete(filename) # URL history if 'url_history' == option_id: for path in FileUtilities.expand_glob_join(self.profile_dir, "places.sqlite"): yield Command.Function(path, Special.delete_mozilla_url_history, _('Delete the usage history')) # vacuum if 'vacuum' == option_id: paths = [] paths += FileUtilities.expand_glob_join( self.profile_dir, "*.sqlite") if not cache_base == self.profile_dir: paths += FileUtilities.expand_glob_join(cache_base, "*.sqlite") for path in paths: yield Command.Function(path, FileUtilities.vacuum_sqlite3, _("Vacuum"))
def get_commands(self, option_id): # cache if 'posix' == os.name and 'cache' == option_id: dirname = expanduser("~/.cache/") for filename in children_in_directory(dirname, True): if not self.whitelisted(filename): yield Command.Delete(filename) # custom if 'custom' == option_id: for (c_type, c_path) in options.get_custom_paths(): if 'file' == c_type: yield Command.Delete(c_path) elif 'folder' == c_type: yield Command.Delete(c_path) for path in children_in_directory(c_path, True): yield Command.Delete(path) else: raise RuntimeError( 'custom folder has invalid type %s' % c_type) # menu menu_dirs = ['~/.local/share/applications', '~/.config/autostart', '~/.gnome/apps/', '~/.gnome2/panel2.d/default/launchers', '~/.gnome2/vfolders/applications/', '~/.kde/share/apps/RecentDocuments/', '~/.kde/share/mimelnk', '~/.kde/share/mimelnk/application/ram.desktop', '~/.kde2/share/mimelnk/application/', '~/.kde2/share/applnk'] if 'posix' == os.name and 'desktop_entry' == option_id: for dirname in menu_dirs: for filename in [fn for fn in children_in_directory(dirname, False) if fn.endswith('.desktop')]: if Unix.is_broken_xdg_desktop(filename): yield Command.Delete(filename) # unwanted locales if 'posix' == os.name and 'localizations' == option_id: for path in Unix.locales.localization_paths(locales_to_keep=options.get_languages()): if os.path.isdir(path): for f in FileUtilities.children_in_directory(path, True): yield Command.Delete(f) yield Command.Delete(path) # Windows logs if 'nt' == os.name and 'logs' == option_id: paths = ( '$ALLUSERSPROFILE\\Application Data\\Microsoft\\Dr Watson\\*.log', '$ALLUSERSPROFILE\\Application Data\\Microsoft\\Dr Watson\\user.dmp', '$LocalAppData\\Microsoft\\Windows\\WER\\ReportArchive\\*\\*', '$LocalAppData\\Microsoft\\Windows\WER\\ReportQueue\\*\\*', '$programdata\\Microsoft\\Windows\\WER\\ReportArchive\\*\\*', '$programdata\\Microsoft\\Windows\\WER\\ReportQueue\\*\\*', '$localappdata\\Microsoft\\Internet Explorer\\brndlog.bak', '$localappdata\\Microsoft\\Internet Explorer\\brndlog.txt', '$windir\\*.log', '$windir\\imsins.BAK', '$windir\\OEWABLog.txt', '$windir\\SchedLgU.txt', '$windir\\ntbtlog.txt', '$windir\\setuplog.txt', '$windir\\REGLOCS.OLD', '$windir\\Debug\\*.log', '$windir\\Debug\\Setup\\UpdSh.log', '$windir\\Debug\\UserMode\\*.log', '$windir\\Debug\\UserMode\\ChkAcc.bak', '$windir\\Debug\\UserMode\\userenv.bak', '$windir\\Microsoft.NET\Framework\*\*.log', '$windir\\pchealth\\helpctr\\Logs\\hcupdate.log', '$windir\\security\\logs\\*.log', '$windir\\security\\logs\\*.old', '$windir\\SoftwareDistribution\\*.log', '$windir\\SoftwareDistribution\\DataStore\\Logs\\*', '$windir\\system32\\TZLog.log', '$windir\\system32\\config\\systemprofile\\Application Data\\Microsoft\\Internet Explorer\\brndlog.bak', '$windir\\system32\\config\\systemprofile\\Application Data\\Microsoft\\Internet Explorer\\brndlog.txt', '$windir\\system32\\LogFiles\\AIT\\AitEventLog.etl.???', '$windir\\system32\\LogFiles\\Firewall\\pfirewall.log*', '$windir\\system32\\LogFiles\\Scm\\SCM.EVM*', '$windir\\system32\\LogFiles\\WMI\\Terminal*.etl', '$windir\\system32\\LogFiles\\WMI\\RTBackup\EtwRT.*etl', '$windir\\system32\\wbem\\Logs\\*.lo_', '$windir\\system32\\wbem\\Logs\\*.log', ) for path in paths: expanded = expandvars(path) for globbed in glob.iglob(expanded): yield Command.Delete(globbed) # memory if sys.platform.startswith('linux') and 'memory' == option_id: yield Command.Function(None, Memory.wipe_memory, _('Memory')) # memory dump # how to manually create this file # http://www.pctools.com/guides/registry/detail/856/ if 'nt' == os.name and 'memory_dump' == option_id: fname = expandvars('$windir\\memory.dmp') if os.path.exists(fname): yield Command.Delete(fname) for fname in glob.iglob(expandvars('$windir\\Minidump\\*.dmp')): yield Command.Delete(fname) # most recently used documents list if 'posix' == os.name and 'recent_documents' == option_id: ru_fn = expanduser("~/.recently-used") if os.path.lexists(ru_fn): yield Command.Delete(ru_fn) # GNOME 2.26 (as seen on Ubuntu 9.04) will retain the list # in memory if it is simply deleted, so it must be shredded # (or at least truncated). # # GNOME 2.28.1 (Ubuntu 9.10) and 2.30 (10.04) do not re-read # the file after truncation, but do re-read it after # shredding. # # https://bugzilla.gnome.org/show_bug.cgi?id=591404 def gtk_purge_items(): """Purge GTK items""" gtk.RecentManager().purge_items() yield 0 for pathname in ["~/.recently-used.xbel", "~/.local/share/recently-used.xbel"]: pathname = expanduser(pathname) if os.path.lexists(pathname): yield Command.Shred(pathname) if HAVE_GTK: # Use the Function to skip when in preview mode yield Command.Function(None, gtk_purge_items, _('Recent documents list')) if 'posix' == os.name and 'rotated_logs' == option_id: for path in Unix.rotated_logs(): yield Command.Delete(path) # temporary files if 'posix' == os.name and 'tmp' == option_id: dirnames = ['/tmp', '/var/tmp'] for dirname in dirnames: for path in children_in_directory(dirname, True): is_open = FileUtilities.openfiles.is_open(path) ok = not is_open and os.path.isfile(path) and \ not os.path.islink(path) and \ FileUtilities.ego_owner(path) and \ not self.whitelisted(path) if ok: yield Command.Delete(path) # temporary files if 'nt' == os.name and 'tmp' == option_id: dirname1 = expandvars( "$USERPROFILE\\Local Settings\\Temp\\") dirname2 = expandvars(r'%temp%') dirname3 = expandvars("%windir%\\temp\\") dirnames = [] if Windows.get_windows_version() >= 6.0: # Windows Vista or later dirnames.append(dirname2) else: # Windows XP dirnames.append(dirname1) dirnames.append(dirname3) # whitelist the folder %TEMP%\Low but not its contents # https://bugs.launchpad.net/bleachbit/+bug/1421726 for dirname in dirnames: low = os.path.join(dirname, 'low').lower() for filename in children_in_directory(dirname, True): if not low == filename.lower(): yield Command.Delete(filename) # trash if 'posix' == os.name and 'trash' == option_id: dirname = expanduser("~/.Trash") for filename in children_in_directory(dirname, False): yield Command.Delete(filename) # fixme http://www.ramendik.ru/docs/trashspec.html # http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html # ~/.local/share/Trash # * GNOME 2.22, Fedora 9 # * KDE 4.1.3, Ubuntu 8.10 dirname = expanduser("~/.local/share/Trash/files") for filename in children_in_directory(dirname, True): yield Command.Delete(filename) dirname = expanduser("~/.local/share/Trash/info") for filename in children_in_directory(dirname, True): yield Command.Delete(filename) dirname = expanduser("~/.local/share/Trash/expunged") # [email protected] tells me that the trash # backend puts files in here temporary, but in some situations # the files are stuck. for filename in children_in_directory(dirname, True): yield Command.Delete(filename) # clipboard if HAVE_GTK and 'clipboard' == option_id: def clear_clipboard(): gtk.gdk.threads_enter() clipboard = gtk.clipboard_get() clipboard.set_text("") gtk.gdk.threads_leave() return 0 yield Command.Function(None, clear_clipboard, _('Clipboard')) # overwrite free space shred_drives = options.get_list('shred_drives') if 'free_disk_space' == option_id and shred_drives: for pathname in shred_drives: # TRANSLATORS: 'Free' means 'unallocated.' # %s expands to a path such as C:\ or /tmp/ display = _("Overwrite free disk space %s") % pathname def wipe_path_func(): for ret in FileUtilities.wipe_path(pathname, idle=True): # Yield control to GTK idle because this process # is very slow. Also display progress. yield ret yield 0 yield Command.Function(None, wipe_path_func, display) # MUICache if 'nt' == os.name and 'muicache' == option_id: keys = ( 'HKCU\\Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache', 'HKCU\\Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache') for key in keys: yield Command.Winreg(key, None) # prefetch if 'nt' == os.name and 'prefetch' == option_id: for path in glob.iglob(expandvars('$windir\\Prefetch\\*.pf')): yield Command.Delete(path) # recycle bin if 'nt' == os.name and 'recycle_bin' == option_id: # This method allows shredding recycled_any = False for path in Windows.get_recycle_bin(): recycled_any = True yield Command.Delete(path) # If there were any files deleted, Windows XP will show the # wrong icon for the recycle bin indicating it is not empty. # The icon will be incorrect until logging in to Windows again # or until it is emptied using the Windows API call for emptying # the recycle bin. # Windows 10 refreshes the recycle bin icon when the user # opens the recycle bin folder. # This is a hack to refresh the icon. def empty_recycle_bin_func(): import tempfile tmpdir = tempfile.mkdtemp() Windows.move_to_recycle_bin(tmpdir) try: Windows.empty_recycle_bin(None, True) except: logging.getLogger(__name__).info('error in empty_recycle_bin()', exc_info=True) yield 0 # Using the Function Command prevents emptying the recycle bin # when in preview mode. if recycled_any: yield Command.Function(None, empty_recycle_bin_func, _('Empty the recycle bin')) # Windows Updates if 'nt' == os.name and 'updates' == option_id: for wu in Windows.delete_updates(): yield wu
def get_commands(self, option_id): # cache if 'posix' == os.name and 'cache' == option_id: # 운영체제이름이 posix이고 option_id가 캐시인 경우 dirname = expanduser("~/.cache/") # ~/.cache/에서 "~"을 사용자 디렉토리의 절대경로로 대체한 것을 dirname에 저장 # dirname = C:\\Documents and Settings\\Administrator\\.cache\ 가 된다. for filename in children_in_directory(dirname, True): # C:\\Documents and Settings\\Administrator\\.cache\ 의 파일 및 선택적으로 하위 디렉토리를 반복 if not self.whitelisted(filename): # filename이 whitelist인지 확인해서 true일 경우 yield Command.Delete(filename) # filename을 삭제하는 메서드를 return # custom if 'custom' == option_id: # option_id가 custom인지 확인 custom = 사용자 정의 for (c_type, c_path) in options.get_custom_paths(): # 사용자 정의 경로의 파일 및 폴더를 반복 if 'file' == c_type: yield Command.Delete(c_path) # file타입일 경우 삭제 elif 'folder' == c_type: yield Command.Delete(c_path) # folder타입일 경우 삭제 for path in children_in_directory(c_path, True): # c_path(사용자 정의 경로)의 파일 및 선택적으로 하위 디렉토리 반복 yield Command.Delete(path) # 반복되는 파일 및 하위 디렉토리 삭제 else: raise RuntimeError( # 파일도 폴더도 아닐경우 런타임에러 발생 'custom folder has invalid type %s' % c_type) # menu menu_dirs = ['~/.local/share/applications', '~/.config/autostart', '~/.gnome/apps/', '~/.gnome2/panel2.d/default/launchers', '~/.gnome2/vfolders/applications/', '~/.kde/share/apps/RecentDocuments/', '~/.kde/share/mimelnk', '~/.kde/share/mimelnk/application/ram.desktop', '~/.kde2/share/mimelnk/application/', '~/.kde2/share/applnk'] # 메뉴 디렉토리에 다음 경로들을 설정 if 'posix' == os.name and 'desktop_entry' == option_id: # 운영체제가 posix이고 option_id가 desktop_entry인 경우 for dirname in menu_dirs: # 메뉴 디렉토리에 있는 경로를 반복 for filename in [fn for fn in children_in_directory(dirname, False) if fn.endswith('.desktop')]: if Unix.is_broken_xdg_desktop(filename): # filename의 XDG 데스크톱 항목 파일의 손상 여부 확인 yield Command.Delete(filename) # filename 삭제 # unwanted locales if 'posix' == os.name and 'localizations' == option_id: # 운영체제가 posix고 option_id가 localizations일때 for path in Unix.locales.localization_paths(locales_to_keep=options.get_languages()): # 이전에 추가한 xml 구성과 일치하는 모든 위치 지정 항목을 반복 if os.path.isdir(path): # path가 존재하는지 확인 for f in FileUtilities.children_in_directory(path, True): # path의 파일 및 하위 디렉토리 반복 yield Command.Delete(f) # path의 파일 및 하위 디렉토리 삭제 yield Command.Delete(path) # path삭제 # Windows logs if 'nt' == os.name and 'logs' == option_id: # os가 윈도우고 option_id가 로그일때 paths = ( '$ALLUSERSPROFILE\\Application Data\\Microsoft\\Dr Watson\\*.log', '$ALLUSERSPROFILE\\Application Data\\Microsoft\\Dr Watson\\user.dmp', '$LocalAppData\\Microsoft\\Windows\\WER\\ReportArchive\\*\\*', '$LocalAppData\\Microsoft\\Windows\WER\\ReportQueue\\*\\*', '$programdata\\Microsoft\\Windows\\WER\\ReportArchive\\*\\*', '$programdata\\Microsoft\\Windows\\WER\\ReportQueue\\*\\*', '$localappdata\\Microsoft\\Internet Explorer\\brndlog.bak', '$localappdata\\Microsoft\\Internet Explorer\\brndlog.txt', '$windir\\*.log', '$windir\\imsins.BAK', '$windir\\OEWABLog.txt', '$windir\\SchedLgU.txt', '$windir\\ntbtlog.txt', '$windir\\setuplog.txt', '$windir\\REGLOCS.OLD', '$windir\\Debug\\*.log', '$windir\\Debug\\Setup\\UpdSh.log', '$windir\\Debug\\UserMode\\*.log', '$windir\\Debug\\UserMode\\ChkAcc.bak', '$windir\\Debug\\UserMode\\userenv.bak', '$windir\\Microsoft.NET\Framework\*\*.log', '$windir\\pchealth\\helpctr\\Logs\\hcupdate.log', '$windir\\security\\logs\\*.log', '$windir\\security\\logs\\*.old', '$windir\\SoftwareDistribution\\*.log', '$windir\\SoftwareDistribution\\DataStore\\Logs\\*', '$windir\\system32\\TZLog.log', '$windir\\system32\\config\\systemprofile\\Application Data\\Microsoft\\Internet Explorer\\brndlog.bak', '$windir\\system32\\config\\systemprofile\\Application Data\\Microsoft\\Internet Explorer\\brndlog.txt', '$windir\\system32\\LogFiles\\AIT\\AitEventLog.etl.???', '$windir\\system32\\LogFiles\\Firewall\\pfirewall.log*', '$windir\\system32\\LogFiles\\Scm\\SCM.EVM*', '$windir\\system32\\LogFiles\\WMI\\Terminal*.etl', '$windir\\system32\\LogFiles\\WMI\\RTBackup\EtwRT.*etl', '$windir\\system32\\wbem\\Logs\\*.lo_', '$windir\\system32\\wbem\\Logs\\*.log', ) for path in paths: # paths에 있는 경로 반복 expanded = expandvars(path) # 경로에 환경변수가 포함되어있으면 확장 for globbed in glob.iglob(expanded): # 확장한 경로의 파일및 디렉토리를 반복 yield Command.Delete(globbed) # 삭제 # memory if sys.platform.startswith('linux') and 'memory' == option_id: # 시스템의 플랫폼이 lunux로 시작하고 option_id가 메모리이면 yield Command.Function(None, Memory.wipe_memory, _('Memory')) # 메모리를 지우는 간단한 파이썬 함수를 만듬 # memory dump # how to manually create this file # http://www.pctools.com/guides/registry/detail/856/ if 'nt' == os.name and 'memory_dump' == option_id: # os가 윈도우고 option_id가 memory_dump 일때 fname = expandvars('$windir\\memory.dmp') # $windir\\memory.dmp에 환경변수가 있으면 확장 if os.path.exists(fname): # 확장한 경로가 존재하는지 확인 yield Command.Delete(fname) # 존재하면 삭제 for fname in glob.iglob(expandvars('$windir\\Minidump\\*.dmp')): # $windir\\Minidump\\*.dmp 를 확장하고 파일 및 디렉토리 반복 yield Command.Delete(fname) # $windir\\Minidump\\*.dmp'의 파일 및 디렉토리들을 삭제 # most recently used documents list if 'posix' == os.name and 'recent_documents' == option_id: # os가 posix고 option_id가 최근 문서일 경우 ru_fn = expanduser("~/.recently-used") # ~/.recently-used 에서 "~"을 사용자 디렉토리의 경로로 대체 if os.path.lexists(ru_fn): # 사용자 디렉토리/.recently-used 가 존재하는지 확인 yield Command.Delete(ru_fn) # 존재하면 삭제 # GNOME 2.26 (as seen on Ubuntu 9.04) will retain the list # in memory if it is simply deleted, so it must be shredded # (or at least truncated). # # GNOME 2.28.1 (Ubuntu 9.10) and 2.30 (10.04) do not re-read # the file after truncation, but do re-read it after # shredding. # # https://bugzilla.gnome.org/show_bug.cgi?id=591404 def gtk_purge_items(): """Purge GTK items""" # GTK 항목 제거 gtk.RecentManager().purge_items() yield 0 for pathname in ["~/.recently-used.xbel", "~/.local/share/recently-used.xbel"]: pathname = expanduser(pathname) # 경로에서 "~"을 사용자 디렉토리로 대체 if os.path.lexists(pathname): # 경로의 파일이 존재하는지 확인 yield Command.Shred(pathname) # 있으면 pathname 잘라내기 if HAVE_GTK: # Use the Function to skip when in preview mode yield Command.Function(None, gtk_purge_items, _('Recent documents list')) # GTK 모듈을 불러오는데 성공했으면 최근 문서 목록을 나타내는 간단한 함수 생성 if 'posix' == os.name and 'rotated_logs' == option_id: # 운영체제가 posix고 option_id 가 순환로그일때 for path in Unix.rotated_logs(): # /var/log/에서 순환 로그(예: 이전 로그) 목록을 반복 yield Command.Delete(path) # 삭제 # temporary files if 'posix' == os.name and 'tmp' == option_id: # 운영체제가 posix이고 option_id가 tmp ( 임시파일) 일때 dirnames = ['/tmp', '/var/tmp'] # 경로 저장 for dirname in dirnames: # 임시파일의 경로 반복 for path in children_in_directory(dirname, True): # 경로의 파일 및 하위 디렉토리 반복 is_open = FileUtilities.openfiles.is_open(path) # path의 파일이 열려있는지 여부 ok = not is_open and os.path.isfile(path) and # path의 파일이 열려있지 않고 path가 존재하며 not os.path.islink(path) and \ # path가 link파일 혹은 폴더가 아니고 FileUtilities.ego_owner(path) and \ # 현재 사용자가 파일을 소유하고 있고 not self.whitelisted(path) # path가 화이트리스트인지 확인 if ok: yield Command.Delete(path) # path 삭제
class System(Cleaner): """Clean the system in general 일반적인 시스템 청소""" def __init__(self): Cleaner.__init__(self) # # options for Linux and BSD # if 'posix' == os.name: #운영체제가 posix면 # TRANSLATORS: desktop entries are .desktop files in Linux that # make up the application menu (the menu that shows BleachBit, # Firefox, and others. The .desktop files also associate file # types, so clicking on an .html file in Nautilus brings up # Firefox. # More information: # http://standards.freedesktop.org/menu-spec/latest/index.html#introduction self.add_option('desktop_entry', _('Broken desktop files'), _( # option_id=desktop entry , name = 손상된 데스크탑 파일들 'Delete broken application menu entries and file associations')) # description = 손상된 응용 프로그램 메뉴 항목 및 파일 연결 삭제 으로 option 추가 self.add_option('cache', _('Cache'), _('Delete the cache')) # 캐시 삭제를 위한 옵션 추가 # TRANSLATORS: Localizations are files supporting specific # languages, so applications appear in Spanish, etc. self.add_option('localizations', _('Localizations'), _( 'Delete files for unwanted languages')) # 원치 않는 언어를 삭제하는 옵션 추가 self.set_warning( 'localizations', _("Configure this option in the preferences."))\ # localizations에 대해 기본 설정에서 이 옵션 구성하라는 경고메세지 설정\ # TRANSLATORS: 'Rotated logs' refers to old system log files. # Linux systems often have a scheduled job to rotate the logs # which means compress all except the newest log and then delete # the oldest log. You could translate this 'old logs.' self.add_option( 'rotated_logs', _('Rotated logs'), _('Delete old system logs')) # 시스템 로그를 삭제기 위한 옵션 추가 self.add_option('recent_documents', _('Recent documents list'), _( 'Delete the list of recently used documents')) # 최근 사용된 문서들의 목록을 삭제하기위한 옵션 추가 self.add_option('trash', _('Trash'), _('Empty the trash')) # 쓰레기통을 비우기 위한 옵션 추가 # # options just for Linux # if sys.platform.startswith('linux'): # 운영체제이름이 linux로 시작할 경우 self.add_option('memory', _('Memory'), # # TRANSLATORS: 'free' means 'unallocated' _('Wipe the swap and free memory')) # 스왑 및 할당되지 않은 메모리를 지우는 옵션 추가 self.set_warning( 'memory', _('This option is experimental and may cause system problems.')) # meomory에 관해 이 옵션은 실험적이며 시스템 문제를 일으킬 수 있다는 경고 메시지 설정 # # options just for Microsoft Windows # if 'nt' == os.name: # os가 윈도우일 경우 self.add_option('logs', _('Logs'), _('Delete the logs')) # 로그를 삭제하는 옵션 추가 self.add_option( 'memory_dump', _('Memory dump'), _('Delete the file memory.dmp')) # 파일 메모리를 삭제하는 옵션 추가 self.add_option('muicache', 'MUICache', _('Delete the cache')) # muicache를 삭제하는 옵션 추가 # TRANSLATORS: Prefetch is Microsoft Windows jargon. self.add_option('prefetch', _('Prefetch'), _('Delete the cache')) # prefetch 캐시를 삭제하는 옵션 추가 # prefetch = 사용했던 프로그램 정보를 담아두는 곳 self.add_option( 'recycle_bin', _('Recycle bin'), _('Empty the recycle bin')) # 휴지통을 비우는 옵션 추가 # TRANSLATORS: 'Update' is a noun, and 'Update uninstallers' is an option to delete # the uninstallers for software updates. self.add_option('updates', _('Update uninstallers'), _( 'Delete uninstallers for Microsoft updates including hotfixes, service packs, and Internet Explorer updates')) # 핫픽스, 서비스 팩 및 Internet Explorer 업데이트를 비롯한 Microsoft 업데이트용 제거 장치를 삭제하는 옵션 추가 # # options for GTK+ GTK = 김프 툴킷 # if HAVE_GTK: # HAVE_GTK 는 GTK모듈을 불러올때 True로 설정했음 즉 모듈을 불러올때 오류가 나지 않았다면 다음 함수들 실행 self.add_option('clipboard', _('Clipboard'), _( 'The desktop environment\'s clipboard used for copy and paste operations')) # 데스크탑 환경에서 복사 및 붙여넣기에 사용되는 클립보드를 옵션에 추가 # # options common to all platforms # # TRANSLATORS: "Custom" is an option allowing the user to specify which # files and folders will be erased. self.add_option('custom', _('Custom'), _( 'Delete user-specified files and folders')) # 사용자 지정 파일 및 폴더를 삭제하는 옵션 추가 # TRANSLATORS: 'free' means 'unallocated' self.add_option('free_disk_space', _('Free disk space'), # # TRANSLATORS: 'free' means 'unallocated' _('Overwrite free disk space to hide deleted files')) # 삭제된 파일을 숨기기 위해 할당되지 않은 디스크 공간 덮어쓰기 옵션 추가 self.set_warning('free_disk_space', _('This option is very slow.')) # free_disk_space 옵션에 대해 이 옵션은 매우 느리다는 경고 메시지 설정 self.add_option( 'tmp', _('Temporary files'), _('Delete the temporary files')) # 임시파일을 삭제하는 옵션 추가 self.description = _("The system in general") # 시스템 클래스의 설명 설정 self.id = 'system' # 시스템 클래스의 id 설정 self.name = _("System") # 시스템 클래스의 이름 설정 def get_commands(self, option_id): # cache if 'posix' == os.name and 'cache' == option_id: # 운영체제이름이 posix이고 option_id가 캐시인 경우 dirname = expanduser("~/.cache/") # ~/.cache/에서 "~"을 사용자 디렉토리의 절대경로로 대체한 것을 dirname에 저장 # dirname = C:\\Documents and Settings\\Administrator\\.cache\ 가 된다. for filename in children_in_directory(dirname, True): # C:\\Documents and Settings\\Administrator\\.cache\ 의 파일 및 선택적으로 하위 디렉토리를 반복 if not self.whitelisted(filename): # filename이 whitelist인지 확인해서 true일 경우 yield Command.Delete(filename) # filename을 삭제하는 메서드를 return # custom if 'custom' == option_id: # option_id가 custom인지 확인 custom = 사용자 정의 for (c_type, c_path) in options.get_custom_paths(): # 사용자 정의 경로의 파일 및 폴더를 반복 if 'file' == c_type: yield Command.Delete(c_path) # file타입일 경우 삭제 elif 'folder' == c_type: yield Command.Delete(c_path) # folder타입일 경우 삭제 for path in children_in_directory(c_path, True): # c_path(사용자 정의 경로)의 파일 및 선택적으로 하위 디렉토리 반복 yield Command.Delete(path) # 반복되는 파일 및 하위 디렉토리 삭제 else: raise RuntimeError( # 파일도 폴더도 아닐경우 런타임에러 발생 'custom folder has invalid type %s' % c_type) # menu menu_dirs = ['~/.local/share/applications', '~/.config/autostart', '~/.gnome/apps/', '~/.gnome2/panel2.d/default/launchers', '~/.gnome2/vfolders/applications/', '~/.kde/share/apps/RecentDocuments/', '~/.kde/share/mimelnk', '~/.kde/share/mimelnk/application/ram.desktop', '~/.kde2/share/mimelnk/application/', '~/.kde2/share/applnk'] # 메뉴 디렉토리에 다음 경로들을 설정 if 'posix' == os.name and 'desktop_entry' == option_id: # 운영체제가 posix이고 option_id가 desktop_entry인 경우 for dirname in menu_dirs: # 메뉴 디렉토리에 있는 경로를 반복 for filename in [fn for fn in children_in_directory(dirname, False) if fn.endswith('.desktop')]: if Unix.is_broken_xdg_desktop(filename): # filename의 XDG 데스크톱 항목 파일의 손상 여부 확인 yield Command.Delete(filename) # filename 삭제 # unwanted locales if 'posix' == os.name and 'localizations' == option_id: # 운영체제가 posix고 option_id가 localizations일때 for path in Unix.locales.localization_paths(locales_to_keep=options.get_languages()): # 이전에 추가한 xml 구성과 일치하는 모든 위치 지정 항목을 반복 if os.path.isdir(path): # path가 존재하는지 확인 for f in FileUtilities.children_in_directory(path, True): # path의 파일 및 하위 디렉토리 반복 yield Command.Delete(f) # path의 파일 및 하위 디렉토리 삭제 yield Command.Delete(path) # path삭제 # Windows logs if 'nt' == os.name and 'logs' == option_id: # os가 윈도우고 option_id가 로그일때 paths = ( '$ALLUSERSPROFILE\\Application Data\\Microsoft\\Dr Watson\\*.log', '$ALLUSERSPROFILE\\Application Data\\Microsoft\\Dr Watson\\user.dmp', '$LocalAppData\\Microsoft\\Windows\\WER\\ReportArchive\\*\\*', '$LocalAppData\\Microsoft\\Windows\WER\\ReportQueue\\*\\*', '$programdata\\Microsoft\\Windows\\WER\\ReportArchive\\*\\*', '$programdata\\Microsoft\\Windows\\WER\\ReportQueue\\*\\*', '$localappdata\\Microsoft\\Internet Explorer\\brndlog.bak', '$localappdata\\Microsoft\\Internet Explorer\\brndlog.txt', '$windir\\*.log', '$windir\\imsins.BAK', '$windir\\OEWABLog.txt', '$windir\\SchedLgU.txt', '$windir\\ntbtlog.txt', '$windir\\setuplog.txt', '$windir\\REGLOCS.OLD', '$windir\\Debug\\*.log', '$windir\\Debug\\Setup\\UpdSh.log', '$windir\\Debug\\UserMode\\*.log', '$windir\\Debug\\UserMode\\ChkAcc.bak', '$windir\\Debug\\UserMode\\userenv.bak', '$windir\\Microsoft.NET\Framework\*\*.log', '$windir\\pchealth\\helpctr\\Logs\\hcupdate.log', '$windir\\security\\logs\\*.log', '$windir\\security\\logs\\*.old', '$windir\\SoftwareDistribution\\*.log', '$windir\\SoftwareDistribution\\DataStore\\Logs\\*', '$windir\\system32\\TZLog.log', '$windir\\system32\\config\\systemprofile\\Application Data\\Microsoft\\Internet Explorer\\brndlog.bak', '$windir\\system32\\config\\systemprofile\\Application Data\\Microsoft\\Internet Explorer\\brndlog.txt', '$windir\\system32\\LogFiles\\AIT\\AitEventLog.etl.???', '$windir\\system32\\LogFiles\\Firewall\\pfirewall.log*', '$windir\\system32\\LogFiles\\Scm\\SCM.EVM*', '$windir\\system32\\LogFiles\\WMI\\Terminal*.etl', '$windir\\system32\\LogFiles\\WMI\\RTBackup\EtwRT.*etl', '$windir\\system32\\wbem\\Logs\\*.lo_', '$windir\\system32\\wbem\\Logs\\*.log', ) for path in paths: # paths에 있는 경로 반복 expanded = expandvars(path) # 경로에 환경변수가 포함되어있으면 확장 for globbed in glob.iglob(expanded): # 확장한 경로의 파일및 디렉토리를 반복 yield Command.Delete(globbed) # 삭제 # memory if sys.platform.startswith('linux') and 'memory' == option_id: # 시스템의 플랫폼이 lunux로 시작하고 option_id가 메모리이면 yield Command.Function(None, Memory.wipe_memory, _('Memory')) # 메모리를 지우는 간단한 파이썬 함수를 만듬 # memory dump # how to manually create this file # http://www.pctools.com/guides/registry/detail/856/ if 'nt' == os.name and 'memory_dump' == option_id: # os가 윈도우고 option_id가 memory_dump 일때 fname = expandvars('$windir\\memory.dmp') # $windir\\memory.dmp에 환경변수가 있으면 확장 if os.path.exists(fname): # 확장한 경로가 존재하는지 확인 yield Command.Delete(fname) # 존재하면 삭제 for fname in glob.iglob(expandvars('$windir\\Minidump\\*.dmp')): # $windir\\Minidump\\*.dmp 를 확장하고 파일 및 디렉토리 반복 yield Command.Delete(fname) # $windir\\Minidump\\*.dmp'의 파일 및 디렉토리들을 삭제 # most recently used documents list if 'posix' == os.name and 'recent_documents' == option_id: # os가 posix고 option_id가 최근 문서일 경우 ru_fn = expanduser("~/.recently-used") # ~/.recently-used 에서 "~"을 사용자 디렉토리의 경로로 대체 if os.path.lexists(ru_fn): # 사용자 디렉토리/.recently-used 가 존재하는지 확인 yield Command.Delete(ru_fn) # 존재하면 삭제 # GNOME 2.26 (as seen on Ubuntu 9.04) will retain the list # in memory if it is simply deleted, so it must be shredded # (or at least truncated). # # GNOME 2.28.1 (Ubuntu 9.10) and 2.30 (10.04) do not re-read # the file after truncation, but do re-read it after # shredding. # # https://bugzilla.gnome.org/show_bug.cgi?id=591404 def gtk_purge_items(): """Purge GTK items""" # GTK 항목 제거 gtk.RecentManager().purge_items() yield 0 for pathname in ["~/.recently-used.xbel", "~/.local/share/recently-used.xbel"]: pathname = expanduser(pathname) # 경로에서 "~"을 사용자 디렉토리로 대체 if os.path.lexists(pathname): # 경로의 파일이 존재하는지 확인 yield Command.Shred(pathname) # 있으면 pathname 잘라내기 if HAVE_GTK: # Use the Function to skip when in preview mode yield Command.Function(None, gtk_purge_items, _('Recent documents list')) # GTK 모듈을 불러오는데 성공했으면 최근 문서 목록을 나타내는 간단한 함수 생성 if 'posix' == os.name and 'rotated_logs' == option_id: # 운영체제가 posix고 option_id 가 순환로그일때 for path in Unix.rotated_logs(): # /var/log/에서 순환 로그(예: 이전 로그) 목록을 반복 yield Command.Delete(path) # 삭제 # temporary files if 'posix' == os.name and 'tmp' == option_id: # 운영체제가 posix이고 option_id가 tmp ( 임시파일) 일때 dirnames = ['/tmp', '/var/tmp'] # 경로 저장 for dirname in dirnames: # 임시파일의 경로 반복 for path in children_in_directory(dirname, True): # 경로의 파일 및 하위 디렉토리 반복 is_open = FileUtilities.openfiles.is_open(path) # path의 파일이 열려있는지 여부 ok = not is_open and os.path.isfile(path) and # path의 파일이 열려있지 않고 path가 존재하며 not os.path.islink(path) and \ # path가 link파일 혹은 폴더가 아니고 FileUtilities.ego_owner(path) and \ # 현재 사용자가 파일을 소유하고 있고 not self.whitelisted(path) # path가 화이트리스트인지 확인 if ok: yield Command.Delete(path) # path 삭제 # temporary files if 'nt' == os.name and 'tmp' == option_id: # os가 윈도우일때 임시파일 삭제 dirname1 = expandvars( "$USERPROFILE\\Local Settings\\Temp\\") # $USERPROFILE\\Local Settings\\Temp\\ 경로 확장 dirname2 = expandvars(r'%temp%') # '%temp% 경로 확장 dirname3 = expandvars("%windir%\\temp\\") # %windir%\\temp\\ 경로 확장 dirnames = [] if Windows.get_windows_version() >= 6.0: # 윈도우의 버전이 6.0 이상이면 비스타나 그 이후버전 # Windows Vista or later dirnames.append(dirname2) # dirnames리스트에 확장한 %temp% 경로 추가 else: # Windows XP dirnames.append(dirname1) # 윈도우 xp의 경우 drinames에 확장한 $USERPROFILE\\Local Settings\\Temp\\ 경로 추가 dirnames.append(dirname3) # dirnames에 확장한 %windir%\\temp\\ 경로 추가 # whitelist the folder %TEMP%\Low but not its contents # https://bugs.launchpad.net/bleachbit/+bug/1421726 for dirname in dirnames: # 확장한 경로 반복 low = os.path.join(dirname, 'low').lower() # 경로와 'low' 를 os에 맞게 연결하고 소문자로 바꿔서 저장 for filename in children_in_directory(dirname, True): # dirname의 파일과 하위 디렉토리 반복 if not low == filename.lower(): # dirname의 파일과 하위 디렉토리를 소문자로 한것이 low와 같으면 yield Command.Delete(filename) # 삭제 # trash if 'posix' == os.name and 'trash' == option_id: # posix에서 option_id가 trash일때 dirname = expanduser("~/.Trash") # ~/.Trash에서 "~"을 사용자 디렉토리로 대체 for filename in children_in_directory(dirname, False): # 사용자 디렉토리/.Trash 의 파일및 하위디렉토리 삭제 yield Command.Delete(filename) # fixme http://www.ramendik.ru/docs/trashspec.html # http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html # ~/.local/share/Trash # * GNOME 2.22, Fedora 9 # * KDE 4.1.3, Ubuntu 8.10 dirname = expanduser("~/.local/share/Trash/files") # 경로 확장 for filename in children_in_directory(dirname, True): # 경로의 파일 및 하위 디렉토리 삭제 yield Command.Delete(filename) dirname = expanduser("~/.local/share/Trash/info") # 경로 확장 for filename in children_in_directory(dirname, True): # 경로의 파일 및 하위 디렉토리 삭제 yield Command.Delete(filename) dirname = expanduser("~/.local/share/Trash/expunged") # [email protected] tells me that the trash # backend puts files in here temporary, but in some situations # the files are stuck. for filename in children_in_directory(dirname, True): yield Command.Delete(filename) # clipboard if HAVE_GTK and 'clipboard' == option_id: # GTK모듈을 불러오고 option_id가 클립보드이면 def clear_clipboard(): # 클립보드를 지우는 함수 생성 gtk.gdk.threads_enter() clipboard = gtk.clipboard_get() clipboard.set_text("") gtk.gdk.threads_leave() return 0 yield Command.Function(None, clear_clipboard, _('Clipboard')) # 클립보드를 지우는 간단한 파이썬 함수 생성 명령 리턴 # overwrite free space 사용가능한 공간 덮어쓰기 shred_drives = options.get_list('shred_drives') # shred_drives 리스트 추출 if 'free_disk_space' == option_id and shred_drives: # option_id가 free_disk_space이고 shred_drives가 존재하면 for pathname in shred_drives: # shred_drives의 요소를 반복 # TRANSLATORS: 'Free' means 'unallocated.' # %s expands to a path such as C:\ or /tmp/ display = _("Overwrite free disk space %s") % pathname # 사용가능한 공간을 덮어쓴다고 출력 def wipe_path_func(): # 경로의 여유공간 를 지우는 함수 for ret in FileUtilities.wipe_path(pathname, idle=True): # Yield control to GTK idle because this process # is very slow. Also display progress. # FileUtilities.wipe_path = 경로의 여유 공간 지우는 함수 # 이 기능은 반복기를 사용하여 GUI를 업데이트합니다. yield ret # pathname 의 여유 공간을 지우고 return yield 0 yield Command.Function(None, wipe_path_func, display) # 간단한 파이썬 함수 생성 # MUICache if 'nt' == os.name and 'muicache' == option_id: keys = ( 'HKCU\\Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache', 'HKCU\\Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache') for key in keys: yield Command.Winreg(key, None) # keys에 있는 경로들의 윈도우 레지스트리를 지운다. # prefetch if 'nt' == os.name and 'prefetch' == option_id: for path in glob.iglob(expandvars('$windir\\Prefetch\\*.pf')): yield Command.Delete(path) # '$windir\\Prefetch\\*.pf' 를 환경변수가 있으면 확장하고 경로에 있는 모든 파일 및 디렉토리를 삭제 # recycle bin if 'nt' == os.name and 'recycle_bin' == option_id: # This method allows shredding recycled_any = False for path in Windows.get_recycle_bin(): # get_recycle_bin() : 휴지통에 있는 파일 목록들 가져오는 함수 recycled_any = True # 휴지통이 비어있는지에 대한 여부 yield Command.Delete(path) # 휴지통에 있는 파일 목록들을 가져와서 삭제 # If there were any files deleted, Windows XP will show the # wrong icon for the recycle bin indicating it is not empty. # The icon will be incorrect until logging in to Windows again # or until it is emptied using the Windows API call for emptying # the recycle bin. # Windows 10 refreshes the recycle bin icon when the user # opens the recycle bin folder. # This is a hack to refresh the icon. def empty_recycle_bin_func(): # 휴지통 비우기 함수 정의 import tempfile tmpdir = tempfile.mkdtemp() # 중복되지않게 무작위로 임시파일 생성 Windows.move_to_recycle_bin(tmpdir) # 생성한 임시파일을 휴지통으로 보냄 try: # 예외처리부분 Windows.empty_recycle_bin(None, True) # 휴지통 비우기 함수 호출 except: logging.getLogger(__name__).info('error in empty_recycle_bin()', exc_info=True) # 에러발생시 휴지통 비우기 에러 라는 로그메시지 저장 yield 0 # Using the Function Command prevents emptying the recycle bin # when in preview mode. if recycled_any: # 휴지통안에 파일이 있으면 yield Command.Function(None, empty_recycle_bin_func, _('Empty the recycle bin')) # 휴지통을 비우는 간단한 파이썬 함수 생성 # name = empty_recycle_bin_func , description = 'Empty the recycle bin' # Windows Updates if 'nt' == os.name and 'updates' == option_id: for wu in Windows.delete_updates(): # 윈도우 업데이트 삭제 yield wu