def strftime(format, tt=None): # pylint: disable=missing-docstring,redefined-builtin t = Unix(int(mktime(tt)), 0) if tt else Now() ret = [] prev, n = 0, format.find('%', 0, -1) while n != -1: ret.append(format[prev:n]) next_ch = format[n + 1] c = _strftime_directive_map.get(next_ch) if c is NotImplemented: raise NotImplementedError('Code: %' + next_ch + ' not yet supported') if c: ret.append(t.Format(c)) else: ret.append(format[n:n+2]) n += 2 prev, n = n, format.find('%', n, -1) ret.append(format[prev:]) return ''.join(ret)
def kernel(self): """\ Return the kernel version. :rtype: string """ return " ".join([ s.strip() for s in re.sub("Linux", "", Unix.Unix().os_release()['name']).split() ])
def is_running(self): """Return whether the program is currently running""" for running in self.running: test = running[0] pathname = running[1] if 'exe' == test and 'posix' == os.name: if Unix.is_running(pathname): print "debug: process '%s' is running" % pathname return True elif 'exe' == test and 'nt' == os.name: if Windows.is_process_running(pathname): print "debug: process '%s' is running" % pathname return True elif 'pathname' == test: expanded = os.path.expanduser(os.path.expandvars(pathname)) for globbed in glob.iglob(expanded): if os.path.exists(globbed): print "debug: file '%s' exists indicating '%s' is running" % (globbed, self.name) return True else: raise RuntimeError("Unknown running-detection test '%s'" % test) return False
def is_running(self): """Return whether the program is currently running""" for running in self.running: test = running[0] pathname = running[1] if 'exe' == test and 'posix' == os.name: if Unix.is_running(pathname): print "debug: process '%s' is running" % pathname return True elif 'exe' == test and 'nt' == os.name: if Windows.is_process_running(pathname): print "debug: process '%s' is running" % pathname return True elif 'pathname' == test: expanded = os.path.expanduser(os.path.expandvars(pathname)) for globbed in glob.iglob(expanded): if os.path.exists(globbed): print "debug: file '%s' exists indicating '%s' is running" % (globbed, self.name) return True else: raise RuntimeError( "Unknown running-detection test '%s'" % test) return False
def get_commands(self, option_id): # This variable will collect fully expanded file names, and # at the end of this function, they will be checked they exist # and processed through Command.Delete(). files = [] # cache if 'posix' == os.name and 'cache' == option_id: dirname = os.path.expanduser("~/.cache/") for filename in children_in_directory(dirname, True): if self.whitelisted(filename): continue files += [filename] # custom if 'custom' == option_id: for (c_type, c_path) in options.get_custom_paths(): if 'file' == c_type: files += [c_path] elif 'folder' == c_type: files += [c_path] for path in children_in_directory(c_path, True): files += [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: callback = lambda locale, language: options.get_language(language) for path in Unix.locales.localization_paths(callback): 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\\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 = os.path.expandvars(path) for globbed in glob.iglob(expanded): files += [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 = os.path.expandvars('$windir\\memory.dmp') if os.path.exists(fname): files += [fname] for fname in glob.iglob(os.path.expandvars('$windir\\Minidump\\*.dmp')): files += [fname] # most recently used documents list if 'posix' == os.name and 'recent_documents' == option_id: files += [os.path.expanduser("~/.recently-used")] # 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 # shreading. # # https://bugzilla.gnome.org/show_bug.cgi?id=591404 for pathname in ["~/.recently-used.xbel", "~/.local/share/recently-used.xbel"]: pathname = os.path.expanduser(pathname) if os.path.lexists(pathname): yield Command.Shred(pathname) if HAVE_GTK: gtk.RecentManager().purge_items() 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: dirname = os.path.expandvars( "$USERPROFILE\\Local Settings\\Temp\\") for filename in children_in_directory(dirname, True): yield Command.Delete(filename) dirname = os.path.expandvars("$windir\\temp\\") for filename in children_in_directory(dirname, True): yield Command.Delete(filename) # trash if 'posix' == os.name and 'trash' == option_id: dirname = os.path.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 = os.path.expanduser("~/.local/share/Trash/files") for filename in children_in_directory(dirname, True): yield Command.Delete(filename) dirname = os.path.expanduser("~/.local/share/Trash/info") for filename in children_in_directory(dirname, True): yield Command.Delete(filename) dirname = os.path.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(os.path.expandvars('$windir\\Prefetch\\*.pf')): yield Command.Delete(path) # recycle bin if 'nt' == os.name and 'recycle_bin' == option_id: for drive in Windows.get_fixed_drives(): # TRANSLATORS: %s expands to a drive letter such as C:\ or D:\ label = _("Recycle bin %s") % drive def emptyrecyclebin(): return Windows.empty_recycle_bin(drive, True) # fixme: enable size preview yield Command.Function(None, emptyrecyclebin, label) # Windows Updates if 'nt' == os.name and 'updates' == option_id: for wu in Windows.delete_updates(): yield wu # return queued files for filename in files: if os.path.lexists(filename): yield Command.Delete(filename)
def get_commands(self, option_id): # This variable will collect fully expanded file names, and # at the end of this function, they will be checked they exist # and processed through Command.Delete(). files = [] # cache if "posix" == os.name and "cache" == option_id: dirname = os.path.expanduser("~/.cache/") for filename in children_in_directory(dirname, True): if self.whitelisted(filename): continue files += [filename] # custom if "custom" == option_id: for (c_type, c_path) in options.get_custom_paths(): if "file" == c_type: files += [c_path] elif "folder" == c_type: files += [c_path] for path in children_in_directory(c_path, True): files += [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 = os.path.expandvars(path) for globbed in glob.iglob(expanded): files += [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 = os.path.expandvars("$windir\\memory.dmp") if os.path.exists(fname): files += [fname] for fname in glob.iglob(os.path.expandvars("$windir\\Minidump\\*.dmp")): files += [fname] # most recently used documents list if "posix" == os.name and "recent_documents" == option_id: files += [os.path.expanduser("~/.recently-used")] # 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 for pathname in ["~/.recently-used.xbel", "~/.local/share/recently-used.xbel"]: pathname = os.path.expanduser(pathname) if os.path.lexists(pathname): yield Command.Shred(pathname) if HAVE_GTK: gtk.RecentManager().purge_items() 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: dirname = os.path.expandvars("$USERPROFILE\\Local Settings\\Temp\\") # whitelist the folder %TEMP%\Low but not its contents # https://bugs.launchpad.net/bleachbit/+bug/1421726 low = os.path.join(dirname, "low").lower() for filename in children_in_directory(dirname, True): if not low == filename.lower(): yield Command.Delete(filename) dirname = os.path.expandvars("$windir\\temp\\") for filename in children_in_directory(dirname, True): yield Command.Delete(filename) # trash if "posix" == os.name and "trash" == option_id: dirname = os.path.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 = os.path.expanduser("~/.local/share/Trash/files") for filename in children_in_directory(dirname, True): yield Command.Delete(filename) dirname = os.path.expanduser("~/.local/share/Trash/info") for filename in children_in_directory(dirname, True): yield Command.Delete(filename) dirname = os.path.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(os.path.expandvars("$windir\\Prefetch\\*.pf")): yield Command.Delete(path) # recycle bin if "nt" == os.name and "recycle_bin" == option_id: # This method allows shredding for path in Windows.get_recycle_bin(): 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. import tempfile tmpdir = tempfile.mkdtemp() Windows.move_to_recycle_bin(tmpdir) try: Windows.empty_recycle_bin(None, True) except: logger = logging.getLogger(__name__) logger.info("error in empty_recycle_bin()", exc_info=True) # Windows Updates if "nt" == os.name and "updates" == option_id: for wu in Windows.delete_updates(): yield wu # return queued files for filename in files: if os.path.lexists(filename): yield Command.Delete(filename)
def localtime(seconds=None): t = (Unix(seconds, 0) if seconds else Now()).Local() return struct_time((t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), (t.Weekday() + 6) % 7, t.YearDay(), 0))