Beispiel #1
0
    def __init__(self, uac=True, shred_paths=None, auto_exit=False):

        if os.name == 'nt':
            if Windows.elevate_privileges(uac):
                # privileges escalated in other process
                sys.exit(0)
            if portable_mode:
                Windows.copy_fonts_in_portable_app(auto_exit)

        Gtk.Application.__init__(
            self, application_id='org.gnome.Bleachbit', flags=Gio.ApplicationFlags.FLAGS_NONE)
        GObject.threads_init()
        
        if auto_exit:
            # This is used for automated testing of whether the GUI can start.
            # It is called from assert_execute_console() in windows/setup_py2exe.py
            self._auto_exit = True        

        if shred_paths:
            self._shred_paths = shred_paths

        if os.name == 'nt':
            # clean up nonce files https://github.com/bleachbit/bleachbit/issues/858
            import atexit
            atexit.register(Windows.cleanup_nonce)

            # BitDefender false positive.  BitDefender didn't mark BleachBit as infected or show
            # anything in its log, but sqlite would fail to import unless BitDefender was in "game mode."
            # https://www.bleachbit.org/forum/074-fails-errors
            try:
                import sqlite3
            except ImportError:
                logger.exception(
                    _("Error loading the SQLite module: the antivirus software may be blocking it."))
Beispiel #2
0
def detectos(required_ver, mock=False):
    """Returns boolean whether the detectos is compatible with the
    current operating system, or the mock version, if given."""
    # Do not compare as string because Windows 10 (build 10.0) comes after
    # Windows 8.1 (build 6.3)
    assert isinstance(required_ver, (str, unicode))
    #현재의 os를 초기화 한다.
    current_os = (mock if mock else Windows.parse_windows_build())
    #required_ver에 required_ver을 붙인다.
    required_ver = required_ver.strip()
    #만약 '|'가 required_ver라면
    if '|' in required_ver:
        # Format of min|max
        # req_min에 required_ver[0]에 '|'붙인 것을 초기화한다.
        req_min = required_ver.split('|')[0]
        # req_max에 required_ver[1]에 '|'붙인 것을 초기화한다.
        req_max = required_ver.split('|')[1]

        #비교를 통해 false와 true을 리턴한다.
        if req_min and current_os < Windows.parse_windows_build(req_min):
            return False
        if req_max and current_os > Windows.parse_windows_build(req_max):
            return False
        return True
    else:
        #버전이 호환된다면 현재의 os를 반환한다.
        # Exact version
        return Windows.parse_windows_build(required_ver) == current_os
Beispiel #3
0
 def is_running(self):
     """Return whether the program is currently running"""
     resp_cli=""
     logger = logging.getLogger(__name__)
     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
                 logger.debug("Debug: process '%s' is running", pathname)
                 if options.get("close_run"):
                     if not subprocess.mswindows:
                         #print "debug: Closing process '%s'" % pathname
                         if "--preset" in sys.argv:
                             resp_cli = raw_input("Do you Want BleachBit to Close " + pathname + " y/n : ")
                         else:
                             resp = GuiBasic.message_dialog(None,"Do you Want BleachBit to Close " + pathname,gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO)
                         if gtk.RESPONSE_YES == resp or resp_cli.lower() == "y":
                         # user cancelled, so don't toggle option
                             logger.debug("Debug: Closing process '%s'",pathname)
                             subprocess.check_output(["killall", "-9", pathname])
                         if not Unix.is_running(pathname):
                             logger.debug("Debug: Closing process '%s' successful",pathname)
                             return False
                 return True
         elif 'exe' == test and 'nt' == os.name:
             if Windows.is_process_running(pathname):
                 #print "debug: process '%s' is running" % pathname
                 logger.debug("Debug: process '%s' is running", pathname)
                 if options.get("close_run"):
                     if subprocess.mswindows:
                         #print "debug: Closing process '%s'" % pathname
                         if "--preset" in sys.argv:
                             resp_cli = raw_input("Do you Want BleachBit to Close " + pathname + " y/n : ")
                         else:
                             resp = GuiBasic.message_dialog(None,"Do you Want BleachBit to Close " + pathname,gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO)
                         if gtk.RESPONSE_YES == resp or resp_cli.lower() == "y":
                             logger.debug("debug: Closing process '%s'",pathname)
                             subprocess.check_output(["taskkill", "/IM", pathname])
                         if not Windows.is_process_running(pathname):
                             logger.debug("debug: Closing process '%s' successful",pathname)
                             return False
                 logger.debug("process '%s' is running", pathname)
                 return True
         elif 'exe' == test and 'nt' == os.name:
             if Windows.is_process_running(pathname):
                 logger.debug("process '%s' is running", pathname)
                 return True
         elif 'pathname' == test:
             expanded = expanduser(expandvars(pathname))
             for globbed in glob.iglob(expanded):
                 if os.path.exists(globbed):
                     logger.debug("file '%s' exists indicating '%s' is running", self.name)
                     return True
         else:
             raise RuntimeError(
                 "Unknown running-detection test '%s'" % test)
     return False
Beispiel #4
0
 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
Beispiel #5
0
 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
Beispiel #6
0
 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
Beispiel #7
0
    def _show_splash_screen(self):
        if os.name != 'nt':
            return

        font_conf_file = Windows.get_font_conf_file()
        if not os.path.exists(font_conf_file):
            logger.error('No fonts.conf file')
            return

        has_cache = Windows.has_fontconfig_cache(font_conf_file)
        if not has_cache:
            Windows.splash_thread.start()
Beispiel #8
0
def browse_folder(parent, title, multiple, stock_button):
    """Ask the user to select a folder.  Return the full path or None."""

    if 'nt' == os.name and None == os.getenv('BB_NATIVE'):
        ret = Windows.browse_folder(
            parent.window.handle if parent else None, title)
        return [ret] if multiple and not ret is None else ret

    # fall back to GTK+
    chooser = gtk.FileChooserDialog(parent=parent,
                                    title=title,
                                    buttons=(
                                        gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                        stock_button, gtk.RESPONSE_OK),
                                    action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
    chooser.set_select_multiple(multiple)
    chooser.set_current_folder(expanduser('~'))
    resp = chooser.run()
    if multiple:
        ret = chooser.get_filenames()
    else:
        ret = chooser.get_filename()
    chooser.hide()
    chooser.destroy()
    if gtk.RESPONSE_OK != resp:
        # user cancelled
        return None
    return ret
Beispiel #9
0
def browse_folder(parent, title, multiple, stock_button):
    """Ask the user to select a folder.  Return the full path or None."""

    if 'nt' == os.name and None == os.getenv('BB_NATIVE'):
        ret = Windows.browse_folder(
            parent.window.handle if parent else None, title)
        return [ret] if multiple and not ret is None else ret

    # fall back to GTK+
    chooser = Gtk.FileChooserDialog(transient_for=parent,
                                    title=title,
                                    action = Gtk.FileChooserAction.SELECT_FOLDER)
    chooser.add_buttons(_("_Cancel"), Gtk.ResponseType.CANCEL, stock_button, Gtk.ResponseType.OK)
    chooser.set_default_response(Gtk.ResponseType.OK)
    chooser.set_select_multiple(multiple)
    chooser.set_current_folder(expanduser('~'))
    resp = chooser.run()
    if multiple:
        ret = chooser.get_filenames()
    else:
        ret = chooser.get_filename()
    chooser.hide()
    chooser.destroy()
    if Gtk.ResponseType.OK != resp:
        # user cancelled
        return None
    return ret
Beispiel #10
0
 def is_running(self):
     """Return whether the program is currently running"""
     logger = logging.getLogger(__name__)
     for running in self.running:
         test = running[0]
         pathname = running[1]
         if 'exe' == test and 'posix' == os.name:
             if Unix.is_running(pathname):
                 logger.debug("process '%s' is running", pathname)
                 return True
         elif 'exe' == test and 'nt' == os.name:
             if Windows.is_process_running(pathname):
                 logger.debug("process '%s' is running", pathname)
                 return True
         elif 'pathname' == test:
             expanded = expanduser(expandvars(pathname))
             for globbed in glob.iglob(expanded):
                 if os.path.exists(globbed):
                     logger.debug(
                         "file '%s' exists indicating '%s' is running",
                         globbed, self.name)
                     return True
         else:
             raise RuntimeError("Unknown running-detection test '%s'" %
                                test)
     return False
Beispiel #11
0
 def is_running(self):
     """Return whether the program is currently running"""
     logger = logging.getLogger(__name__)
     for running in self.running:
         test = running[0]
         pathname = running[1]
         if 'exe' == test and 'posix' == os.name:
             if Unix.is_running(pathname):
                 logger.debug("process '%s' is running", pathname)
                 return True
         elif 'exe' == test and 'nt' == os.name:
             if Windows.is_process_running(pathname):
                 logger.debug("process '%s' is running", pathname)
                 return True
         elif 'pathname' == test:
             expanded = expanduser(expandvars(pathname))
             for globbed in glob.iglob(expanded):
                 if os.path.exists(globbed):
                     logger.debug(
                         "file '%s' exists indicating '%s' is running", globbed, self.name)
                     return True
         else:
             raise RuntimeError(
                 "Unknown running-detection test '%s'" % test)
     return False
Beispiel #12
0
    def __init__(self, uac=True, shred_paths=None, auto_exit=False):
        if uac and os.name == 'nt' and Windows.elevate_privileges():
            # privileges escalated in other process
            sys.exit(0)
        Gtk.Application.__init__(self,
                                 application_id='org.gnome.Bleachbit',
                                 flags=Gio.ApplicationFlags.FLAGS_NONE)
        GObject.threads_init()

        if shred_paths:
            self._shred_paths = shred_paths
            return
        if os.name == 'nt':
            # BitDefender false positive.  BitDefender didn't mark BleachBit as infected or show
            # anything in its log, but sqlite would fail to import unless BitDefender was in "game mode."
            # https://www.bleachbit.org/forum/074-fails-errors
            try:
                import sqlite3
            except ImportError:
                logger.exception(
                    _("Error loading the SQLite module: the antivirus software may be blocking it."
                      ))
        if auto_exit:
            # This is used for automated testing of whether the GUI can start.
            self._auto_exit = True
Beispiel #13
0
 def is_running(self):
     """Return whether the program is currently running"""    # 프로그램이 현재 실행 중인지 여부를 반환하는 함수
     logger = logging.getLogger(__name__)            # __name__에서 로거 추출
     for running in self.running:           # running 리스트의 값들 반복      
         test = running[0]         # running[0] = detection_type   ( add_running 함수 참고)               
         pathname = running[1]             
         if 'exe' == test and 'posix' == os.name:  # os이름이 posix이고 exe 타입인지 확인
             if Unix.is_running(pathname): # Unix에서 is_running함수썼을때 True이면 
                 logger.debug("process '%s' is running", pathname) # 프로세스가 실행중이라는 debug 메세지를 로그하고 True반환
                 return True
         elif 'exe' == test and 'nt' == os.name: # os이름이 nt 이고 exe타입인지 확인
             if Windows.is_process_running(pathname):  # 만약 Windows에서 is_process_running 함수를 사용했을때 true이면
                 logger.debug("process '%s' is running", pathname) # 프로세스가 실행중이라는 debug 메세지를 로그하고 true반환
                 return True
         elif 'pathname' == test:                # test 
             expanded = expanduser(expandvars(pathname)) # pathname 안에 환경변수가 있으면 확장하고 현재 사용자 디렉토리의 절대경로로 대체
                                                         # ex) C:\\Documents and Settings\\Administrator\\pathname 
             for globbed in glob.iglob(expanded):  # iglob() : expanded의 모든 값을 실제로 동시에 저장하지 않고
                                                   #  glob()값과 동일한 값을 산출하는 반복기를 반환함
                 if os.path.exists(globbed): # globbed로 저장한 경로에 특정파일이 존재하는지 확인
                     logger.debug(
                         "file '%s' exists indicating '%s' is running", globbed, self.name)
                             # 존재하면 파일이 존재하며 실행중임을 나타내는 메세지출력
                     return True
         else:
             raise RuntimeError( 
                 "Unknown running-detection test '%s'" % test) # test가 exe , pathname도 아니면 알수없는 실행타입메세지와 함께 런타임에러발생
     return False
Beispiel #14
0
def browse_folder(parent, title, multiple, stock_button):
    """Ask the user to select a folder.  Return the full path or None."""

    if os.name == 'nt' and not os.getenv('BB_NATIVE'):
        ret = Windows.browse_folder(parent, title)
        return [ret] if multiple and not ret is None else ret

    # fall back to GTK+
    chooser = Gtk.FileChooserDialog(transient_for=parent,
                                    title=title,
                                    action=Gtk.FileChooserAction.SELECT_FOLDER)
    chooser.add_buttons(_("_Cancel"), Gtk.ResponseType.CANCEL, stock_button,
                        Gtk.ResponseType.OK)
    chooser.set_default_response(Gtk.ResponseType.OK)
    chooser.set_select_multiple(multiple)
    chooser.set_current_folder(expanduser('~'))
    resp = chooser.run()
    if multiple:
        ret = chooser.get_filenames()
    else:
        ret = chooser.get_filename()
    chooser.hide()
    chooser.destroy()
    if Gtk.ResponseType.OK != resp:
        # user cancelled
        return None
    return ret
Beispiel #15
0
    def detect(self, section):
        """Check whether to show the section

        The logic:
        If the DetectOS does not match, the section is inactive.
        If any Detect or DetectFile matches, the section is active.
        If neither Detect or DetectFile was given, the section is active.
        Otherwise, the section is inactive.
        """
        if self.parser.has_option(section, 'detectos'):
            required_ver = self.parser.get(section, 'detectos')
            if not detectos(required_ver):
                return False
        any_detect_option = False
        if self.parser.has_option(section, 'specialdetect'):
            any_detect_option = True
            sd_code = self.parser.get(section, 'specialdetect')
            if special_detect(sd_code):
                return True
        for option in self.parser.options(section):
            if re.match(self.re_detect, option):
                # Detect= checks for a registry key
                any_detect_option = True
                key = self.parser.get(section, option)
                if Windows.detect_registry_key(key):
                    return True
            elif re.match(self.re_detectfile, option):
                # DetectFile= checks for a file
                any_detect_option = True
                key = self.parser.get(section, option)
                if detect_file(key):
                    return True
        return not any_detect_option
Beispiel #16
0
def browse_folder(parent, title, multiple, stock_button):
    """Ask the user to select a folder.  Return the full path or None."""

    if 'nt' == os.name and None == os.getenv('BB_NATIVE'):
        ret = Windows.browse_folder(parent.window.handle if parent else None,
                                    title)
        return [ret] if multiple and not ret is None else ret

    # fall back to GTK+
    chooser = gtk.FileChooserDialog(
        parent=parent,
        title=title,
        buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, stock_button,
                 gtk.RESPONSE_OK),
        action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
    chooser.set_select_multiple(multiple)
    chooser.set_current_folder(expanduser('~'))
    resp = chooser.run()
    if multiple:
        ret = chooser.get_filenames()
    else:
        ret = chooser.get_filename()
    chooser.hide()
    chooser.destroy()
    if gtk.RESPONSE_OK != resp:
        # user cancelled
        return None
    return ret
Beispiel #17
0
    def __init__(self, uac=True, shred_paths=None, exit=False):
        if uac and 'nt' == os.name and Windows.elevate_privileges():
            # privileges escalated in other process
            sys.exit(0)
        Gtk.Application.__init__(self, application_id='org.gnome.Bleachbit', flags=Gio.ApplicationFlags.FLAGS_NONE)
        if not exit:
            from bleachbit import RecognizeCleanerML
            RecognizeCleanerML.RecognizeCleanerML()
            register_cleaners()
        GObject.threads_init()

        if shred_paths:
            self.shred_paths(shred_paths)
            return
        if 'nt' == os.name:
            # BitDefender false positive.  BitDefender didn't mark BleachBit as infected or show
            # anything in its log, but sqlite would fail to import unless BitDefender was in "game mode."
            # https://www.bleachbit.org/forum/074-fails-errors
            try:
                import sqlite3
            except ImportError:
                logger.exception(_("Error loading the SQLite module: the antivirus software may be blocking it."))
        if 'posix' == os.name and bleachbit.expanduser('~') == '/root':
            self.append_text(
                _('You are running BleachBit with administrative privileges for cleaning shared parts of the system, and references to the user profile folder will clean only the root account.'))
        if 'nt' == os.name and options.get('shred'):
            from win32com.shell.shell import IsUserAnAdmin
            if not IsUserAnAdmin():
                self.append_text(
                    _('Run BleachBit with administrator privileges to improve the accuracy of overwriting the contents of files.'))
                self.append_text('\n')
        if exit:
            # This is used for automated testing of whether the GUI can start.
            print('Success')
            GObject.idle_add(lambda: self.quit(), priority=GObject.PRIORITY_LOW)
Beispiel #18
0
    def _init_windows_misc(self, auto_exit, shred_paths, uac):
        application_id_suffix = ''
        if os.name == 'nt':
            if Windows.elevate_privileges(uac):
                # privileges escalated in other process
                sys.exit(0)
            if portable_mode:
                Windows.copy_fonts_in_portable_app(auto_exit)

            if auto_exit and shred_paths:
                # When we have a running application and executing the Windows
                # context menu command we start a new process with new application_id.
                # That is because the command line arguments of the context menu command
                # are not passed to the already running instance.
                application_id_suffix = 'ContextMenuShred'
        return application_id_suffix
Beispiel #19
0
    def detect(self, section):
        """Check whether to show the section

        The logic:
        If the DetectOS does not match, the section is inactive.
        If any Detect or DetectFile matches, the section is active.
        If neither Detect or DetectFile was given, the section is active.
        Otherwise, the section is inactive.
        """
        if self.parser.has_option(section, 'detectos'):
            required_ver = self.parser.get(section, 'detectos').decode(FSE)
            if not detectos(required_ver):
                return False
        any_detect_option = False
        if self.parser.has_option(section, 'specialdetect'):
            any_detect_option = True
            sd_code = self.parser.get(section, 'specialdetect')
            if special_detect(sd_code):
                return True
        for option in self.parser.options(section):
            if re.match(self.re_detect, option):
                # Detect= checks for a registry key
                any_detect_option = True
                key = self.parser.get(section, option).decode(FSE)
                if Windows.detect_registry_key(key):
                    return True
            elif re.match(self.re_detectfile, option):
                # DetectFile= checks for a file
                any_detect_option = True
                key = self.parser.get(section, option).decode(FSE)
                if detect_file(key):
                    return True
        return not any_detect_option
Beispiel #20
0
    def __init__(self, uac=True, shred_paths=None, exit=False):
        if uac and 'nt' == os.name and Windows.elevate_privileges():
            # privileges escalated in other process
            sys.exit(0)
        if not exit:
            from bleachbit import RecognizeCleanerML
            RecognizeCleanerML.RecognizeCleanerML()
            register_cleaners()
        self.create_window()
        gobject.threads_init()

        # Redirect logging to the GUI.
        bb_logger = logging.getLogger('bleachbit')
        gtklog = GtkLoggerHandler(self.append_text)
        bb_logger.addHandler(gtklog)
        if 'nt' == os.name and 'windows_exe' == getattr(sys, 'frozen', None):
            # On Microsoft Windows this avoids py2exe redirecting stderr to
            # bleachbit.exe.log.
            # sys.frozen = console_exe means the console is shown
            from bleachbit import logger_sh
            bb_logger.removeHandler(logger_sh)
        if shred_paths:
            self.shred_paths(shred_paths)
            return
        if options.get("first_start") and 'posix' == os.name:
            pref = PreferencesDialog(self.window, self.cb_refresh_operations)
            pref.run()
            options.set('first_start', False)
        if bleachbit.online_update_notification_enabled and options.get(
                "check_online_updates"):
            self.check_online_updates()
        if 'nt' == os.name:
            # BitDefender false positive.  BitDefender didn't mark BleachBit as infected or show
            # anything in its log, but sqlite would fail to import unless BitDefender was in "game mode."
            # https://www.bleachbit.org/forum/074-fails-errors
            try:
                import sqlite3
            except ImportError:
                logger.exception(
                    _("Error loading the SQLite module: the antivirus software may be blocking it."
                      ))
        if 'posix' == os.name and bleachbit.expanduser('~') == '/root':
            self.append_text(
                _('You are running BleachBit with administrative privileges for cleaning shared parts of the system, and references to the user profile folder will clean only the root account.'
                  ))
        if 'nt' == os.name and options.get('shred'):
            from win32com.shell.shell import IsUserAnAdmin
            if not IsUserAnAdmin():
                self.append_text(
                    _('Run BleachBit with administrator privileges to improve the accuracy of overwriting the contents of files.'
                      ))
                self.append_text('\n')
        if exit:
            # This is used for automated testing of whether the GUI can start.
            gobject.idle_add(lambda: gtk.main_quit(),
                             priority=gobject.PRIORITY_LOW)
Beispiel #21
0
def detectos(required_ver, mock=False):
    """Returns boolean whether the detectos is compatible with the
    current operating system, or the mock version, if given."""
    # Do not compare as string because Windows 10 (build 10.0) comes after
    # Windows 8.1 (build 6.3).
    assert (isinstance(required_ver, (str, unicode)))
    current_os = (mock if mock else Windows.parse_windows_build())
    required_ver = required_ver.strip()
    if required_ver.startswith('|'):
        # This is the maximum version
        # For example, |5.1 means Windows XP (5.1) but not Vista (6.0)
        return current_os <= Windows.parse_windows_build(required_ver[1:])
    elif required_ver.endswith('|'):
        # This is the minimum version
        # For example, 6.1| means Windows 7 or later
        return current_os >= Windows.parse_windows_build(required_ver[:-1])
    else:
        # Exact version
        return Windows.parse_windows_build(required_ver) == current_os
Beispiel #22
0
def detectos(required_ver, mock=False):
    """Returns boolean whether the detectos is compatible with the
    current operating system, or the mock version, if given."""
    # Do not compare as string because Windows 10 (build 10.0) comes after
    # Windows 8.1 (build 6.3).
    assert(isinstance(required_ver, (str, unicode)))
    current_os = (mock if mock else Windows.parse_windows_build())
    required_ver = required_ver.strip()
    if required_ver.startswith('|'):
        # This is the maximum version
        # For example, |5.1 means Windows XP (5.1) but not Vista (6.0)
        return current_os <= Windows.parse_windows_build(required_ver[1:])
    elif required_ver.endswith('|'):
        # This is the minimum version
        # For example, 6.1| means Windows 7 or later
        return current_os >= Windows.parse_windows_build(required_ver[:-1])
    else:
        # Exact version
        return Windows.parse_windows_build(required_ver) == current_os
Beispiel #23
0
def detectos(required_ver, mock=False):
    """Returns boolean whether the detectos is compatible with the
    current operating system, or the mock version, if given."""
    # Do not compare as string because Windows 10 (build 10.0) comes after
    # Windows 8.1 (build 6.3).
    assert isinstance(required_ver, str)
    current_os = mock or Windows.parse_windows_build()
    required_ver = required_ver.strip()
    if '|' not in required_ver:
        # Exact version
        return Windows.parse_windows_build(required_ver) == current_os
    # Format of min|max
    req_min = required_ver.split('|')[0]
    req_max = required_ver.split('|')[1]
    if req_min and current_os < Windows.parse_windows_build(req_min):
        return False
    if req_max and current_os > Windows.parse_windows_build(req_max):
        return False
    return True
Beispiel #24
0
def detectos(required_ver, mock=False):
    """Returns boolean whether the detectos is compatible with the
    current operating system, or the mock version, if given."""
    # Do not compare as string because Windows 10 (build 10.0) comes after
    # Windows 8.1 (build 6.3).
    assert isinstance(required_ver, (str, unicode))
    current_os = (mock if mock else Windows.parse_windows_build())
    required_ver = required_ver.strip()
    if '|' in required_ver:
        # Format of min|max
        req_min = required_ver.split('|')[0]
        req_max = required_ver.split('|')[1]
        if req_min and current_os < Windows.parse_windows_build(req_min):
            return False
        if req_max and current_os > Windows.parse_windows_build(req_max):
            return False
        return True
    else:
        # Exact version
        return Windows.parse_windows_build(required_ver) == current_os
Beispiel #25
0
    def __init__(self, uac=True, shred_paths=None, exit=False):
        if uac and 'nt' == os.name and Windows.elevate_privileges():
            # privileges escalated in other process
            sys.exit(0)
        if not exit:
            from bleachbit import RecognizeCleanerML
            RecognizeCleanerML.RecognizeCleanerML()
            register_cleaners()
        self.create_window()
        gobject.threads_init()

        # Redirect logging to the GUI.
        bb_logger = logging.getLogger('bleachbit')
        gtklog = GtkLoggerHandler(self.append_text)
        bb_logger.addHandler(gtklog)
        if 'nt' == os.name and 'windows_exe' == getattr(sys, 'frozen', None):
            # On Microsoft Windows this avoids py2exe redirecting stderr to
            # bleachbit.exe.log.
            # sys.frozen = console_exe means the console is shown
            from bleachbit import logger_sh
            bb_logger.removeHandler(logger_sh)
        if shred_paths:
            self.shred_paths(shred_paths)
            return
        if options.get("first_start") and 'posix' == os.name:
            pref = PreferencesDialog(self.window, self.cb_refresh_operations)
            pref.run()
            options.set('first_start', False)
        if bleachbit.online_update_notification_enabled and options.get("check_online_updates"):
            self.check_online_updates()
        if 'nt' == os.name:
            # BitDefender false positive.  BitDefender didn't mark BleachBit as infected or show
            # anything in its log, but sqlite would fail to import unless BitDefender was in "game mode."
            # https://www.bleachbit.org/forum/074-fails-errors
            try:
                import sqlite3
            except ImportError:
                logger.exception(_("Error loading the SQLite module: the antivirus software may be blocking it."))
        if 'posix' == os.name and bleachbit.expanduser('~') == '/root':
            self.append_text(
                _('You are running BleachBit with administrative privileges for cleaning shared parts of the system, and references to the user profile folder will clean only the root account.'))
        if 'nt' == os.name and options.get('shred'):
            from win32com.shell.shell import IsUserAnAdmin
            if not IsUserAnAdmin():
                self.append_text(
                    _('Run BleachBit with administrator privileges to improve the accuracy of overwriting the contents of files.'))
                self.append_text('\n')
        if exit:
            # This is used for automated testing of whether the GUI can start.
            gobject.idle_add(
                lambda: gtk.main_quit(), priority=gobject.PRIORITY_LOW)
Beispiel #26
0
def special_detect(code):
    """Check whether the SpecialDetect== software exists"""
    # The last two are used only for testing
    sd_keys = {'DET_CHROME': r'HKCU\Software\Google\Chrome',
               'DET_MOZILLA': r'HKCU\Software\Mozilla\Firefox',
               'DET_OPERA': r'HKCU\Software\Opera Software',
               'DET_THUNDERBIRD': r'HKLM\SOFTWARE\Clients\Mail\Mozilla Thunderbird',
               'DET_WINDOWS': r'HKCU\Software\Microsoft',
               'DET_SPACE_QUEST': r'HKCU\Software\Sierra Games\Space Quest'}
    if code in sd_keys:
        return Windows.detect_registry_key(sd_keys[code])
    else:
        logger.error('Unknown SpecialDetect=%s', code)
    return False
Beispiel #27
0
def special_detect(code):
    """Check whether the SpecialDetect== software exists"""
    # The last two are used only for testing
    sd_keys = {'DET_CHROME': r'HKCU\Software\Google\Chrome',
               'DET_MOZILLA': r'HKCU\Software\Mozilla\Firefox',
               'DET_OPERA': r'HKCU\Software\Opera Software',
               'DET_THUNDERBIRD': r'HKLM\SOFTWARE\Clients\Mail\Mozilla Thunderbird',
               'DET_WINDOWS': r'HKCU\Software\Microsoft',
               'DET_SPACE_QUEST': r'HKCU\Software\Sierra Games\Space Quest'}
    if sd_keys.has_key(code):
        return Windows.detect_registry_key(sd_keys[code])
    else:
        logger.error('Unknown SpecialDetect=%s', code)
    return False
Beispiel #28
0
def free_space(pathname):
    """Return free space in bytes"""
    if 'nt' == os.name:
        from bleachbit import Windows
        if Windows.parse_windows_build() >= 6:
            # This works better with UTF-8 paths.
            import psutil
            return psutil.disk_usage(pathname).free
        else:
            # This works better with Windows XP but not UTF-8.
            # Deprecated.
            _, _, free_bytes = win32file.GetDiskFreeSpaceEx(pathname)
            return free_bytes
    mystat = os.statvfs(pathname)
    return mystat.f_bfree * mystat.f_bsize
Beispiel #29
0
def free_space(pathname):
    """Return free space in bytes"""
    if 'nt' == os.name:
        from bleachbit import Windows
        if Windows.parse_windows_build() >= 6:
            # This works better with UTF-8 paths.
            import psutil
            return psutil.disk_usage(pathname).free
        else:
            # This works better with Windows XP but not UTF-8.
            # Deprecated.
            _fb, _tb, total_free_bytes = win32file.GetDiskFreeSpaceEx(pathname)
            return total_free_bytes
    mystat = os.statvfs(pathname)
    return mystat.f_bfree * mystat.f_bsize
Beispiel #30
0
 def cb_clipboard_uri_received(self, clipboard, targets, data):
     """Callback for when URIs are received from clipboard"""
     shred_paths = None
     if 'text/uri-list' in targets:
         # Linux
         shred_uris = clipboard.wait_for_contents(
             'text/uri-list').get_uris()
         shred_paths = FileUtilities.uris_to_paths(shred_uris)
     elif 'FileNameW' in targets:
         # Windows
         # Use non-GTK+ functions because because GTK+ 2 does not work.
         shred_paths = Windows.get_clipboard_paths()
     if shred_paths:
         self.shred_paths(shred_paths)
     else:
         logger.warning(_('No paths found in clipboard.'))
Beispiel #31
0
 def cb_clipboard_uri_received(self, clipboard, targets, data):
     """Callback for when URIs are received from clipboard"""
     shred_paths = None
     if Gdk.atom_intern_static_string('text/uri-list') in targets:
         # Linux
         shred_uris = clipboard.wait_for_contents(
             Gdk.atom_intern_static_string('text/uri-list')).get_uris()
         shred_paths = FileUtilities.uris_to_paths(shred_uris)
     elif Gdk.atom_intern_static_string('FileNameW') in targets:
         # Windows
         # Use non-GTK+ functions because because GTK+ 2 does not work.
         shred_paths = Windows.get_clipboard_paths()
     if shred_paths:
         GUI.shred_paths(self._window, shred_paths)
     else:
         logger.warning(_('No paths found in clipboard.'))
Beispiel #32
0
def browse_file(parent, title):
    """Prompt user to select a single file"""

    if 'nt' == os.name and None == os.getenv('BB_NATIVE'):
        return Windows.browse_file(parent.window.handle, title)

    chooser = gtk.FileChooserDialog(title=title,
                                    parent=parent,
                                    action=gtk.FILE_CHOOSER_ACTION_OPEN,
                                    buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
    chooser.set_current_folder(expanduser('~'))
    resp = chooser.run()
    path = chooser.get_filename()
    chooser.destroy()

    if gtk.RESPONSE_OK != resp:
        # user cancelled
        return None

    return path
Beispiel #33
0
def browse_file(parent, title):
    """Prompt user to select a single file"""

    if 'nt' == os.name and None == os.getenv('BB_NATIVE'):
        return Windows.browse_file(parent.window.handle, title)

    chooser = Gtk.FileChooserDialog(title=title,
                                    transient_for=parent,
                                    action=Gtk.FileChooserAction.OPEN)
    chooser.add_buttons(_("_Cancel"), Gtk.ResponseType.CANCEL, _("_Open"), Gtk.ResponseType.OK)
    chooser.set_default_response(Gtk.ResponseType.OK)
    chooser.set_current_folder(expanduser('~'))
    resp = chooser.run()
    path = chooser.get_filename()
    chooser.destroy()

    if Gtk.ResponseType.OK != resp:
        # user cancelled
        return None

    return path
Beispiel #34
0
def browse_file(parent, title):
    """Prompt user to select a single file"""

    if os.name == 'nt' and not os.getenv('BB_NATIVE'):
        return Windows.browse_file(parent, title)

    chooser = Gtk.FileChooserDialog(title=title,
                                    transient_for=parent,
                                    action=Gtk.FileChooserAction.OPEN)
    chooser.add_buttons(_("_Cancel"), Gtk.ResponseType.CANCEL, _("_Open"),
                        Gtk.ResponseType.OK)
    chooser.set_default_response(Gtk.ResponseType.OK)
    chooser.set_current_folder(expanduser('~'))
    resp = chooser.run()
    path = chooser.get_filename()
    chooser.destroy()

    if Gtk.ResponseType.OK != resp:
        # user cancelled
        return None

    return path
Beispiel #35
0
def browse_files(parent, title):
    """Prompt user to select multiple files to delete"""

    if 'nt' == os.name and None == os.getenv('BB_NATIVE'):
        return Windows.browse_files(parent.window.handle, title)

    chooser = Gtk.FileChooserDialog(title=title,
                                    transient_for=parent,
                                    action=Gtk.FileChooserAction.OPEN)
    chooser.add_buttons(_("_Cancel"), Gtk.ResponseType.CANCEL, _("_Delete"),
                        Gtk.ResponseType.OK)
    chooser.set_default_response(Gtk.ResponseType.OK)
    chooser.set_select_multiple(True)
    chooser.set_current_folder(expanduser('~'))
    resp = chooser.run()
    paths = chooser.get_filenames()
    chooser.destroy()

    if Gtk.ResponseType.OK != resp:
        # user cancelled
        return None

    return paths
Beispiel #36
0
 def handle_section(self, section):
     """Parse a section"""
     # if simple detection fails then discard the section
     if self.parser.has_option(section, 'detect'):
         key = self.parser.get(section, 'detect').decode(FSE)
         if not Windows.detect_registry_key(key):
             return
     if self.parser.has_option(section, 'detectfile'):
         if not detect_file(self.parser.get(section, 'detectfile').decode(FSE)):
             return
     if self.parser.has_option(section, 'detectos'):
         required_ver = self.parser.get(section, 'detectos').decode(FSE)
         if not detectos(required_ver):
             return
     # in case of multiple detection, discard if none match
     if self.parser.has_option(section, 'detectfile1'):
         matches = 0
         for n in range(1, MAX_DETECT):
             option_id = 'detectfile%d' % n
             if self.parser.has_option(section, option_id):
                 if detect_file(self.parser.get(section, option_id).decode(FSE)):
                     matches += 1
         if 0 == matches:
             return
     if self.parser.has_option(section, 'detect1'):
         matches = 0
         for n in range(1, MAX_DETECT):
             option_id = 'detect%d' % n
             if self.parser.has_option(section, option_id):
                 if Windows.detect_registry_key(self.parser.get(section, option_id).decode(FSE)):
                     matches += 1
         if 0 == matches:
             return
     # excludekeys ignores a file, path, or registry key
     excludekeys = []
     if self.parser.has_option(section, 'excludekey1'):
         for n in range(1, MAX_DETECT):
             option_id = 'excludekey%d' % n
             if self.parser.has_option(section, option_id):
                 excludekeys.append(
                     self.excludekey_to_nwholeregex(self.parser.get(section, option_id).decode(FSE)))
     # there are two ways to specify sections: langsecref= and section=
     if self.parser.has_option(section, 'langsecref'):
         # verify the langsecref number is known
         # langsecref_num is 3021, games, etc.
         langsecref_num = self.parser.get(section, 'langsecref').decode(FSE)
     elif self.parser.has_option(section, 'section'):
         langsecref_num = self.parser.get(section, 'section').decode(FSE)
     else:
         logger.error('neither option LangSecRef nor Section found in section %s', section)
         return
     # find the BleachBit internal cleaner ID
     lid = self.section_to_cleanerid(langsecref_num)
     self.cleaners[lid].add_option(
         section2option(section), section.replace('*', ''), '')
     for option in self.parser.options(section):
         if option.startswith('filekey'):
             self.handle_filekey(lid, section, option, excludekeys)
         elif option.startswith('regkey'):
             self.handle_regkey(lid, section, option)
         elif option == 'warning':
             self.cleaners[lid].set_warning(
                 section2option(section), self.parser.get(section, 'warning').decode(FSE))
         elif option in ('default', 'detectfile', 'detect', 'langsecref', 'section') \
             or ['detect%d' % x for x in range(1, MAX_DETECT)] \
                 or ['detectfile%d' % x for x in range(1, MAX_DETECT)]:
             pass
         else:
             logger.warning('unknown option %s in section %s', option, section)
             return
Beispiel #37
0
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
Beispiel #38
0
    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
Beispiel #39
0
 def handle_section(self, section):
     """Parse a section"""
     # if simple detection fails then discard the section
     if self.parser.has_option(section, 'detect'):
         key = self.parser.get(section, 'detect').decode(FSE)
         if not Windows.detect_registry_key(key):
             return
     if self.parser.has_option(section, 'detectfile'):
         if not detect_file(
                 self.parser.get(section, 'detectfile').decode(FSE)):
             return
     if self.parser.has_option(section, 'detectos'):
         required_ver = self.parser.get(section, 'detectos').decode(FSE)
         if not detectos(required_ver):
             return
     # in case of multiple detection, discard if none match
     if self.parser.has_option(section, 'detectfile1'):
         matches = 0
         for n in range(1, MAX_DETECT):
             option_id = 'detectfile%d' % n
             if self.parser.has_option(section, option_id):
                 if detect_file(
                         self.parser.get(section, option_id).decode(FSE)):
                     matches += 1
         if 0 == matches:
             return
     if self.parser.has_option(section, 'detect1'):
         matches = 0
         for n in range(1, MAX_DETECT):
             option_id = 'detect%d' % n
             if self.parser.has_option(section, option_id):
                 if Windows.detect_registry_key(
                         self.parser.get(section, option_id).decode(FSE)):
                     matches += 1
         if 0 == matches:
             return
     # excludekeys ignores a file, path, or registry key
     excludekeys = []
     if self.parser.has_option(section, 'excludekey1'):
         for n in range(1, MAX_DETECT):
             option_id = 'excludekey%d' % n
             if self.parser.has_option(section, option_id):
                 excludekeys.append(
                     self.excludekey_to_nwholeregex(
                         self.parser.get(section, option_id).decode(FSE)))
     # there are two ways to specify sections: langsecref= and section=
     if self.parser.has_option(section, 'langsecref'):
         # verify the langsecref number is known
         # langsecref_num is 3021, games, etc.
         langsecref_num = self.parser.get(section, 'langsecref').decode(FSE)
     elif self.parser.has_option(section, 'section'):
         langsecref_num = self.parser.get(section, 'section').decode(FSE)
     else:
         logger.error(
             'neither option LangSecRef nor Section found in section %s',
             section)
         return
     # find the BleachBit internal cleaner ID
     lid = self.section_to_cleanerid(langsecref_num)
     self.cleaners[lid].add_option(section2option(section),
                                   section.replace('*', ''), '')
     for option in self.parser.options(section):
         if option.startswith('filekey'):
             self.handle_filekey(lid, section, option, excludekeys)
         elif option.startswith('regkey'):
             self.handle_regkey(lid, section, option)
         elif option == 'warning':
             self.cleaners[lid].set_warning(
                 section2option(section),
                 self.parser.get(section, 'warning').decode(FSE))
         elif option in ('default', 'detectfile', 'detect', 'langsecref', 'section') \
             or ['detect%d' % x for x in range(1, MAX_DETECT)] \
                 or ['detectfile%d' % x for x in range(1, MAX_DETECT)]:
             pass
         else:
             logger.warning('unknown option %s in section %s', option,
                            section)
             return
Beispiel #40
0
# Map our pgettext() custom function to _p()
_p = pgettext


#
# URLs
#
base_url = "https://update.bleachbit.org"
help_contents_url = "%s/help/%s" \
    % (base_url, APP_VERSION)
release_notes_url = "%s/release-notes/%s" \
    % (base_url, APP_VERSION)
update_check_url = "%s/update/%s" % (base_url, APP_VERSION)

# set up environment variables
if 'nt' == os.name:
    from bleachbit import Windows
    Windows.setup_environment()

if 'posix' == os.name:
    # XDG base directory specification
    envs = {
        'XDG_DATA_HOME': os.path.expanduser('~/.local/share'),
        'XDG_CONFIG_HOME': os.path.expanduser('~/.config'),
        'XDG_CACHE_HOME': os.path.expanduser('~/.cache')
    }
    for varname, value in envs.iteritems():
        if not os.getenv(varname):
            os.environ[varname] = value
Beispiel #41
0

#
# URLs
#
base_url = "https://update.bleachbit.org"
help_contents_url = "%s/help/%s" \
    % (base_url, APP_VERSION)
release_notes_url = "%s/release-notes/%s" \
    % (base_url, APP_VERSION)
update_check_url = "%s/update/%s" % (base_url, APP_VERSION)

# set up environment variables
if 'nt' == os.name:
    from bleachbit import Windows
    Windows.setup_environment()

if 'posix' == os.name:
    # XDG base directory specification
    envs = {
        'XDG_DATA_HOME': os.path.expanduser('~/.local/share'),
        'XDG_CONFIG_HOME': os.path.expanduser('~/.config'),
        'XDG_CACHE_HOME': os.path.expanduser('~/.cache')
    }
    for varname, value in envs.items():
        if not os.getenv(varname):
            os.environ[varname] = value

if 'posix' == os.name:
    fs_scan_re_flags = 0 # should be re.IGNORECASE on macOS
else:
Beispiel #42
0
    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