Example #1
0
def update_dialog(parent, updates):
    """Updates contains the version numbers and URLs"""
    import gtk
    from bleachbit.GuiBasic import open_url
    dlg = gtk.Dialog(title=_("Update BleachBit"),
                     parent=parent,
                     flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
    dlg.set_default_size(250, 125)

    label = gtk.Label(_("A new version is available."))
    dlg.vbox.pack_start(label)

    for update in updates:
        ver = update[0]
        url = update[1]
        box_update = gtk.HBox()
        # TRANSLATORS: %s expands to version such as '0.8.4' or '0.8.5beta' or
        # similar
        button_stable = gtk.Button(_("Update to version %s") % ver)
        button_stable.connect(
            'clicked', lambda dummy: open_url(url, parent, False))
        button_stable.connect('clicked', lambda dummy: dlg.response(0))
        box_update.pack_start(button_stable, False, padding=10)
        dlg.vbox.pack_start(box_update, False)

    dlg.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)

    dlg.show_all()
    dlg.run()
    dlg.destroy()

    return False
Example #2
0
File: GUI.py Project: az0/bleachbit
    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)
Example #3
0
File: GUI.py Project: az0/bleachbit
    def create_headerbar(self):
        """Create the headerbar"""
        hb = Gtk.HeaderBar()
        hb.props.show_close_button = True
        hb.props.title = APP_NAME

        box = Gtk.Box()
        Gtk.StyleContext.add_class(box.get_style_context(), "linked")

        # create the preview button
        preview_icon = Gio.ThemedIcon(name='edit-find')


        # TRANSLATORS: This is the preview button on the main window.  It
        # previews changes.
        preview_button = Gtk.Button()
        preview_button.add(Gtk.Image.new_from_gicon(preview_icon, Gtk.IconSize.BUTTON))
        preview_button.connect('clicked', lambda *dummy: self.preview_or_run_operations(False))
        preview_button.set_tooltip_text(
            _("Preview files in the selected operations (without deleting any files)"))
        box.add(preview_button)

        # create the delete button
        run_button = Gtk.Button()
        icon = Gio.ThemedIcon(name="edit-clear-all-symbolic")
        # TRANSLATORS: This is the clean button on the main window.
        # It makes permanent changes: usually deleting files, sometimes
        # altering them.
        run_button.add(Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON))
        run_button.set_tooltip_text(_("Clean files in the selected operations"))
        run_button.connect("clicked", self.run_operations)
        box.add(run_button)

        hb.pack_start(box)
        return hb
Example #4
0
def delete_confirmation_dialog(parent, mention_preview):
    """Return boolean whether OK to delete files."""
    dialog = gtk.Dialog(title=_("Delete confirmation"), parent=parent,
                        flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
    dialog.set_default_size(300, -1)

    hbox = gtk.HBox(homogeneous=False, spacing=10)
    icon = gtk.Image()
    icon.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG)
    hbox.pack_start(icon, False)
    if mention_preview:
        question_text = _(
            "Are you sure you want to permanently delete files according to the selected operations?  The actual files that will be deleted may have changed since you ran the preview.")
    else:
        question_text = _(
            "Are you sure you want to permanently delete these files?")

    question = gtk.Label(question_text)
    question.set_line_wrap(True)
    hbox.pack_start(question, False)
    dialog.vbox.pack_start(hbox, False)
    dialog.vbox.set_spacing(10)

    dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
    dialog.add_button(gtk.STOCK_DELETE, gtk.RESPONSE_ACCEPT)
    dialog.set_default_response(gtk.RESPONSE_CANCEL)

    dialog.show_all()
    ret = dialog.run()
    dialog.destroy()
    return ret == gtk.RESPONSE_ACCEPT
Example #5
0
File: GUI.py Project: az0/bleachbit
    def about(self, action, param):
        """Create and show the about dialog"""

        dialog = Gtk.AboutDialog(comments='Program to clean unnecessary files',
                                 copyright='Copyright (C) 2008-2018 Andrew Ziem',
                                 name=APP_NAME,
                                 version=bleachbit.APP_VERSION,
                                 website=bleachbit.APP_URL,
                                 transient_for=self._window)
        try:
            with open(bleachbit.license_filename) as f:
                dialog.set_license(f.read())
        except IOError:
            dialog.set_license(
                _("GNU General Public License version 3 or later.\nSee https://www.gnu.org/licenses/gpl-3.0.txt"))
        #dialog.set_name(APP_NAME)
        # TRANSLATORS: Maintain the names of translators here.
        # Launchpad does this automatically for translations
        # typed in Launchpad. This is a special string shown
        # in the 'About' box.
        dialog.set_translator_credits(_("translator-credits"))
        if appicon_path and os.path.exists(appicon_path):
            icon = Gtk.Image.new_from_file(appicon_path)
            dialog.set_logo(icon.get_pixbuf())
        dialog.run()
        dialog.hide()
Example #6
0
    def worker_done(self, worker, really_delete):
        """Callback for when Worker is done"""
        self.progressbar.set_text("")
        self.progressbar.set_fraction(1)
        self.progressbar.set_text(_("Done."))
        self.textview.scroll_mark_onscreen(self.textbuffer.get_insert())
        self.set_sensitive(True)

        # Close the program after cleaning is completed.
        # if the option is selected under preference.

        if really_delete:
            if options.get("exit_done"):
                sys.exit()

        # notification for long-running process
        elapsed = (time.time() - self.start_time)
        logger.debug('elapsed time: %d seconds', elapsed)
        if elapsed < 10 or self.window.is_active():
            return
        try:
            import pynotify
        except ImportError:
            logger.debug('pynotify not available')
        else:
            if pynotify.init(APP_NAME):
                notify = pynotify.Notification('BleachBit', _("Done."),
                                               icon='bleachbit')
                if 'posix' == os.name and bleachbit.expanduser('~') == '/root':
                    notify.set_hint("desktop-entry", "bleachbit-root")
                else:
                    notify.set_hint("desktop-entry", "bleachbit")
                notify.show()
                notify.set_timeout(10000)
Example #7
0
    def context_menu_event(self, treeview, event):
        """When user right clicks on the tree view"""
        if event.button != 3:
            return False
        pathinfo = treeview.get_path_at_pos(int(event.x), int(event.y))
        if None == pathinfo:
            return False
        path, col, cellx, celly = pathinfo
        treeview.grab_focus()
        treeview.set_cursor(path, col, 0)
        # context menu applies only to children, not parents
        if 2 != len(path):
            return False
        # find the seleted option
        model = treeview.get_model()
        option_id = model[path][2]
        cleaner_id = model[path[0]][2]
        # make a menu
        menu = gtk.Menu()
        # TRANSLATORS: this is the context menu
        preview_item = gtk.MenuItem(_("Preview"))
        preview_item.connect('activate', self.cb_run_option,
                             False, cleaner_id, option_id)
        menu.append(preview_item)
        # TRANSLATORS: this is the context menu
        clean_item = gtk.MenuItem(_("Clean"))
        clean_item.connect('activate', self.cb_run_option,
                           True, cleaner_id, option_id)
        menu.append(clean_item)

        # show the context menu
        menu.attach_to_widget(treeview, menu.destroy)
        menu.show_all()
        menu.popup(None, None, None, event.button, event.time)
        return True
Example #8
0
 def about(self, __event):
     """Create and show the about dialog"""
     if 'nt' != os.name and (2, 16, 6) != gtk.gtk_version:
         # workaround for broken GTK+
         # (https://bugs.launchpad.net/bleachbit/+bug/797012)
         gtk.about_dialog_set_url_hook(lambda dialog,
                                       link: GuiBasic.open_url(link, self.window, False))
     dialog = gtk.AboutDialog()
     dialog.set_comments(_("Program to clean unnecessary files"))
     dialog.set_copyright("Copyright (C) 2008-2018 Andrew Ziem")
     try:
         with open(bleachbit.license_filename) as f:
             dialog.set_license(f.read())
     except (IOError, TypeError):
         # In case the license file cannot be read, there will be an
         # IOError. In case the license file does not exist, the filename
         # will be none, causing a TypeError.
         dialog.set_license(
             _("GNU General Public License version 3 or later.\nSee http://www.gnu.org/licenses/gpl-3.0.txt"))
     dialog.set_name(APP_NAME)
     # TRANSLATORS: Maintain the names of translators here.
     # Launchpad does this automatically for translations
     # typed in Launchpad. This is a special string shown
     # in the 'About' box.
     dialog.set_translator_credits(_("translator-credits"))
     dialog.set_version(bleachbit.APP_VERSION)
     dialog.set_website(bleachbit.APP_URL)
     dialog.set_transient_for(self.window)
     if appicon_path and os.path.exists(appicon_path):
         icon = gtk.gdk.pixbuf_new_from_file(appicon_path)
         dialog.set_logo(icon)
     dialog.run()
     dialog.hide()
Example #9
0
    def create_toolbar(self):
        """Create the toolbar"""
        toolbar = gtk.Toolbar()

        # create the preview button
        preview_icon = gtk.Image()
        preview_icon.set_from_stock(
            gtk.STOCK_FIND, gtk.ICON_SIZE_LARGE_TOOLBAR)
        # TRANSLATORS: This is the preview button on the main window.  It
        # previews changes.
        preview_button = gtk.ToolButton(
            icon_widget=preview_icon, label=_p('button', "Preview"))
        preview_button.connect(
            "clicked", lambda *dummy: self.preview_or_run_operations(False))
        toolbar.insert(preview_button, -1)
        preview_button.set_tooltip_text(
            _("Preview files in the selected operations (without deleting any files)"))
        preview_button.set_is_important(True)

        # create the delete button
        icon = gtk.Image()
        icon.set_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_LARGE_TOOLBAR)
        # TRANSLATORS: This is the clean button on the main window.
        # It makes permanent changes: usually deleting files, sometimes
        # altering them.
        run_button = gtk.ToolButton(
            icon_widget=icon, label=_p("button", "Clean"))
        run_button.connect("clicked", self.run_operations)
        toolbar.insert(run_button, -1)
        run_button.set_tooltip_text(
            _("Clean files in the selected operations"))
        run_button.set_is_important(True)

        return toolbar
Example #10
0
def update_dialog(parent, updates):
    """Updates contains the version numbers and URLs"""
    from gi.repository import Gtk
    from bleachbit.GuiBasic import open_url
    dlg = Gtk.Dialog(title=_("Update BleachBit"),
                     transient_for=parent,
                     modal=True,
                     destroy_with_parent=True)
    dlg.set_default_size(250, 125)

    label = Gtk.Label(label=_("A new version is available."))
    dlg.vbox.pack_start(label, True, True, 0)

    for update in updates:
        ver = update[0]
        url = update[1]
        box_update = Gtk.Box()
        # TRANSLATORS: %s expands to version such as '0.8.4' or '0.8.5beta' or
        # similar
        button_stable = Gtk.Button(_("Update to version %s") % ver)
        button_stable.connect(
            'clicked', lambda dummy: open_url(url, parent, False))
        button_stable.connect('clicked', lambda dummy: dlg.response(0))
        box_update.pack_start(button_stable, False, True, 10)
        dlg.vbox.pack_start(box_update, False, True, 0)

    dlg.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)

    dlg.show_all()
    dlg.run()
    dlg.destroy()

    return False
Example #11
0
 def execute(self, really_delete):
     """Make changes and return results"""
     if FileUtilities.whitelisted(self.path):
         yield whitelist(self.path)
         return
     ret = {
         # TRANSLATORS: This is the label in the log indicating will be
         # deleted (for previews) or was actually deleted
         'label': _('Delete'),
         'n_deleted': 1,
         'n_special': 0,
         'path': self.path,
         'size': FileUtilities.getsize(self.path)}
     if really_delete:
         try:
             FileUtilities.delete(self.path, self.shred)
         except WindowsError as e:
             # WindowsError: [Error 32] The process cannot access the file because it is being
             # used by another process: u'C:\\Documents and
             # Settings\\username\\Cookies\\index.dat'
             if 32 != e.winerror and 5 != e.winerror:
                 raise
             try:
                 bleachbit.Windows.delete_locked_file(self.path)
             except:
                 raise
             else:
                 if self.shred:
                     import warnings
                     warnings.warn(
                         _('At least one file was locked by another process, so its contents could not be overwritten. It will be marked for deletion upon system reboot.'))
                 # TRANSLATORS: The file will be deleted when the
                 # system reboots
                 ret['label'] = _('Mark for deletion')
     yield ret
Example #12
0
def delete_confirmation_dialog(parent, mention_preview):
    """Return boolean whether OK to delete files."""
    dialog = Gtk.Dialog(title=_("Delete confirmation"), transient_for=parent,
                        modal=True,
                        destroy_with_parent=True)
    dialog.set_default_size(300, -1)

    hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, homogeneous=False, spacing=10)
    if mention_preview:
        question_text = _(
            "Are you sure you want to permanently delete files according to the selected operations?  The actual files that will be deleted may have changed since you ran the preview.")
    else:
        question_text = _(
            "Are you sure you want to permanently delete these files?")

    question = Gtk.Label(label=question_text)
    question.set_line_wrap(True)
    hbox.pack_start(question, False, True, 0)
    dialog.get_content_area().pack_start(hbox, False, True, 0)
    dialog.get_content_area().set_spacing(10)

    dialog.add_button(_('_Cancel'), Gtk.ResponseType.CANCEL)
    dialog.add_button(_('_Delete'), Gtk.ResponseType.ACCEPT)
    dialog.set_default_response(Gtk.ResponseType.CANCEL)

    dialog.show_all()
    ret = dialog.run()
    dialog.destroy()
    return ret == Gtk.ResponseType.ACCEPT
Example #13
0
def open_url(self, action, url, parent_window=None, prompt=True):
    """Open an HTTP URL.  Try to run as non-root."""
    # drop privileges so the web browser is running as a normal process
    if 'posix' == os.name and 0 == os.getuid():
        msg = _(
            "Because you are running as root, please manually open this link in a web browser:\n%s") % url
        message_dialog(None, msg, Gtk.MessageType.INFO)
        return
    if prompt:
        # find hostname
        import re
        ret = re.search('^http(s)?://([a-z.]+)', url)
        if None == ret:
            host = url
        else:
            host = ret.group(2)
        # TRANSLATORS: %s expands to www.bleachbit.org or similar
        msg = _("Open web browser to %s?") % host
        resp = message_dialog(parent_window, msg,
                              Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL)
        if Gtk.ResponseType.OK != resp:
            return
    # open web browser
    if 'nt' == os.name:
        # in Gtk.show_uri() avoid 'glib.GError: No application is registered as
        # handling this file'
        import webbrowser
        webbrowser.open(url)
    else:
        Gtk.show_uri(None, url, Gdk.CURRENT_TIME)
Example #14
0
File: GUI.py Project: az0/bleachbit
    def cb_shred_folder(self, action, param):
        """Callback for shredding a folder"""

        paths = GuiBasic.browse_folder(self._window,
                                       _("Choose folder to shred"),
                                       multiple=True,
                                       stock_button=_('_Delete'))
        if not paths:
            return
        GUI.shred_paths(self._window, paths)
Example #15
0
 def add_custom_file_cb(button):
     """Callback for adding a file"""
     title = _("Choose a file")
     pathname = GuiBasic.browse_file(self.parent, title)
     if pathname:
         for this_pathname in pathnames:
             if pathname == this_pathname[1]:
                 logger.warning("'%s' already exists in whitelist", pathname)
                 return
         liststore.append([_('File'), pathname])
         pathnames.append(['file', pathname])
         options.set_custom_paths(pathnames)
Example #16
0
 def add_custom_folder_cb(button):
     """Callback for adding a folder"""
     title = _("Choose a folder")
     pathname = GuiBasic.browse_folder(self.parent, title,
                                       multiple=False, stock_button=gtk.STOCK_ADD)
     if pathname:
         for this_pathname in pathnames:
             if pathname == this_pathname[1]:
                 logger.warning("'%s' already exists in whitelist", pathname)
                 return
         liststore.append([_('Folder'), pathname])
         pathnames.append(['folder', pathname])
         options.set_custom_paths(pathnames)
Example #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)
        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)
Example #18
0
def load_cleaners():
    """Scan for CleanerML and load them"""
    for pathname in list_cleanerml_files():
        try:
            xmlcleaner = CleanerML(pathname)
        except:
            logger.exception(_("Error reading cleaner: %s"), pathname)
            continue
        cleaner = xmlcleaner.get_cleaner()
        if cleaner.is_usable():
            Cleaner.backends[cleaner.id] = cleaner
        else:
            logger.debug(
                _("Cleaner is not usable on this OS because it has no actions: %s"), pathname)
Example #19
0
File: GUI.py Project: az0/bleachbit
    def cb_wipe_free_space(self, action, param):
        """callback to wipe free space in arbitrary folder"""
        path = GuiBasic.browse_folder(self._window,
                                      _("Choose a folder"),
                                      multiple=False, stock_button=_('_OK'))
        if not path:
            # user cancelled
            return

        backends['_gui'] = Cleaner.create_wipe_cleaner(path)

        # execute
        operations = {'_gui': ['free_disk_space']}
        self.preview_or_run_operations(True, operations)
Example #20
0
    def __languages_page(self):
        """Return widget containing the languages page"""

        def preserve_toggled_cb(cell, path, liststore):
            """Callback for toggling the 'preserve' column"""
            __iter = liststore.get_iter_from_string(path)
            value = not liststore.get_value(__iter, 0)
            liststore.set(__iter, 0, value)
            langid = liststore[path][1]
            options.set_language(langid, value)

        vbox = gtk.VBox()

        notice = gtk.Label(
            _("All languages will be deleted except those checked."))
        vbox.pack_start(notice, False)

        # populate data
        liststore = gtk.ListStore('gboolean', str, str)
        for lang, native in sorted(Unix.Locales.native_locale_names.items()):
            liststore.append([(options.get_language(lang)), lang, native])

        # create treeview
        treeview = gtk.TreeView(liststore)

        # create column views
        self.renderer0 = gtk.CellRendererToggle()
        self.renderer0.set_property('activatable', True)
        self.renderer0.connect('toggled', preserve_toggled_cb, liststore)
        self.column0 = gtk.TreeViewColumn(
            _("Preserve"), self.renderer0, active=0)
        treeview.append_column(self.column0)

        self.renderer1 = gtk.CellRendererText()
        self.column1 = gtk.TreeViewColumn(_("Code"), self.renderer1, text=1)
        treeview.append_column(self.column1)

        self.renderer2 = gtk.CellRendererText()
        self.column2 = gtk.TreeViewColumn(_("Name"), self.renderer2, text=2)
        treeview.append_column(self.column2)
        treeview.set_search_column(2)

        # finish
        swindow = gtk.ScrolledWindow()
        swindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        swindow.set_size_request(300, 200)
        swindow.add(treeview)
        vbox.pack_start(swindow)
        return vbox
Example #21
0
def update_winapp2(url, hash_expected, append_text, cb_success):
    """Download latest winapp2.ini file.  Hash is sha512 or None to disable checks"""
    # first, determine whether an update is necessary
    from bleachbit import personal_cleaners_dir
    fn = os.path.join(personal_cleaners_dir, 'winapp2.ini')
    delete_current = False
    if os.path.exists(fn):
        f = open(fn, 'r')
        hash_current = hashlib.sha512(f.read()).hexdigest()
        if not hash_expected or hash_current == hash_expected:
            # update is same as current
            return
        f.close()
        delete_current = True
    # download update
    opener = build_opener()
    opener.addheaders = [('User-Agent', user_agent())]
    doc = opener.open(fullurl=url, timeout=20).read()
    # verify hash
    hash_actual = hashlib.sha512(doc).hexdigest()
    if hash_expected and not hash_actual == hash_expected:
        raise RuntimeError("hash for %s actually %s instead of %s" %
                           (url, hash_actual, hash_expected))
    # delete current
    if delete_current:
        from bleachbit.FileUtilities import delete
        delete(fn, True)
    # write file
    if not os.path.exists(personal_cleaners_dir):
        os.mkdir(personal_cleaners_dir)
    f = open(fn, 'w')
    f.write(doc)
    append_text(_('New winapp2.ini was downloaded.'))
    cb_success()
Example #22
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
Example #23
0
 def diagnostic_dialog(self, parent):
     """Show diagnostic information"""
     dialog = gtk.Dialog(_("System information"), parent)
     dialog.resize(600, 400)
     txtbuffer = gtk.TextBuffer()
     from bleachbit import Diagnostic
     txt = Diagnostic.diagnostic_info()
     txtbuffer.set_text(txt)
     textview = gtk.TextView(txtbuffer)
     textview.set_editable(False)
     swindow = gtk.ScrolledWindow()
     swindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
     swindow.add_with_viewport(textview)
     dialog.vbox.pack_start(swindow)
     dialog.add_buttons(
         gtk.STOCK_COPY, 100, gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
     dialog.show_all()
     while True:
         rc = dialog.run()
         if 100 == rc:
             clipboard = gtk.clipboard_get()
             clipboard.set_text(txt)
         else:
             break
     dialog.hide()
Example #24
0
    def execute(self, really_delete):
        """Execute the Windows registry cleaner"""
        if 'nt' != os.name:
            raise StopIteration
        _str = None  # string representation
        ret = None  # return value meaning 'deleted' or 'delete-able'
        if self.valuename:
            _str = '%s<%s>' % (self.keyname, self.valuename)
            ret = bleachbit.Windows.delete_registry_value(self.keyname,
                                                self.valuename, really_delete)
        else:
            ret = bleachbit.Windows.delete_registry_key(self.keyname, really_delete)
            _str = self.keyname
        if not ret:
            # Nothing to delete or nothing was deleted.  This return
            # makes the auto-hide feature work nicely.
            raise StopIteration

        ret = {
            'label': _('Delete registry key'),
            'n_deleted': 0,
            'n_special': 1,
            'path': _str,
            'size': 0}

        yield ret
Example #25
0
    def preview_or_run_operations(self, really_delete, operations=None):
        """Preview operations or run operations (delete files)"""

        assert(isinstance(really_delete, bool))
        from bleachbit import Worker
        self.start_time = None
        if None == operations:
            operations = {}
            for operation in self.get_selected_operations():
                operations[operation] = self.get_operation_options(operation)
        assert(isinstance(operations, dict))
        if 0 == len(operations):
            GuiBasic.message_dialog(self.window,
                                    _("You must select an operation"),
                                    gtk.MESSAGE_WARNING, gtk.BUTTONS_OK)
            return
        try:
            self.set_sensitive(False)
            self.textbuffer.set_text("")
            self.progressbar.show()
            self.worker = Worker.Worker(self, really_delete, operations)
        except Exception:
            logger.exception('Error in Worker()')
        else:
            self.start_time = time.time()
            worker = self.worker.run()
            gobject.idle_add(worker.next)
Example #26
0
 def set_cleaner(self, path, model, parent_window, value=None):
     """Activate or deactive option of cleaner."""
     if None == value:
         # if not value given, toggle current value
         value = not model[path][1]
     assert(type(value) is types.BooleanType)
     assert(type(model) is gtk.TreeStore)
     cleaner_id = None
     i = path
     if type(i) is str:
         # type is either str or gtk.TreeIter
         i = model.get_iter(path)
     parent = model.iter_parent(i)
     if None != parent:
         # this is an option (child), not a cleaner (parent)
         cleaner_id = model[parent][2]
         option_id = model[path][2]
     if cleaner_id and value:
         # when toggling an option, present any warnings
         warning = backends[cleaner_id].get_warning(option_id)
         # TRANSLATORS: %(cleaner) may be Firefox, System, etc.
         # %(option) may be cache, logs, cookies, etc.
         # %(warning) may be 'This option is really slow'
         msg = _("Warning regarding %(cleaner)s - %(option)s:\n\n%(warning)s") % \
             {'cleaner': model[parent][0],
              'option': model[path][0],
              'warning': warning}
         if warning:
             resp = GuiBasic.message_dialog(parent_window,
                                            msg,
                                            gtk.MESSAGE_WARNING, gtk.BUTTONS_OK_CANCEL)
             if gtk.RESPONSE_OK != resp:
                 # user cancelled, so don't toggle option
                 return
     model[path][1] = value
Example #27
0
 def handle_cleaner_option_label(self, label):
     """<label> element under <option>"""
     self.option_name = _(getText(label.childNodes))
     translate = label.getAttribute('translate')
     translators = label.getAttribute('translators')
     if not translate or boolstr_to_bool(translate):
         self.xlate_cb(self.option_name, translators)
Example #28
0
def create_simple_cleaner(paths):
    """Shred arbitrary files (used in CLI and GUI)"""
    cleaner = Cleaner()
    cleaner.add_option(option_id='files', name='', description='')
    cleaner.name = _("System")  # shows up in progress bar

    from bleachbit import Action

    class CustomFileAction(Action.ActionProvider):
        action_key = '__customfileaction'

        def get_commands(self):
            for path in paths:
                if not isinstance(path, (str, unicode)):
                    raise RuntimeError(
                        'expected path as string but got %s' % str(path))
                if not os.path.isabs(path):
                    path = os.path.abspath(path)
                if os.path.isdir(path):
                    for child in children_in_directory(path, True):
                        yield Command.Shred(child)
                    yield Command.Shred(path)
                else:
                    yield Command.Shred(path)
    provider = CustomFileAction(None)
    cleaner.add_action('files', provider)
    return cleaner
Example #29
0
def create_wipe_cleaner(path):
    """Wipe free disk space of arbitrary paths (used in GUI)"""
    cleaner = Cleaner()
    cleaner.add_option(
        option_id='free_disk_space', name='', description='')
    cleaner.name = ''

    # create a temporary cleaner object
    display = _("Overwrite free disk space %s") % path

    def wipe_path_func():
        for ret in FileUtilities.wipe_path(path, idle=True):
            yield ret
        yield 0

    from bleachbit import Action

    class CustomWipeAction(Action.ActionProvider):
        action_key = '__customwipeaction'

        def get_commands(self):
            yield Command.Function(None, wipe_path_func, display)
    provider = CustomWipeAction(None)
    cleaner.add_action('free_disk_space', provider)
    return cleaner
Example #30
0
def args_to_operations(args, preset):
    """Read arguments and return list of operations"""
    register_cleaners()
    operations = {}
    if preset:
        # restore presets from the GUI
        for key in sorted(backends):
            c_id = backends[key].get_id()
            for (o_id, o_name) in backends[key].get_options():
                if Options.options.get_tree(c_id, o_id):
                    args.append('.'.join([c_id, o_id]))
    for arg in args:
        if 2 != len(arg.split('.')):
            logger.warning(_("not a valid cleaner: %s"), arg)
            continue
        (cleaner_id, option_id) = arg.split('.')
        # enable all options (for example, firefox.*)
        if '*' == option_id:
            if cleaner_id in operations:
                del operations[cleaner_id]
            operations[cleaner_id] = []
            for (option_id2, o_name) in backends[cleaner_id].get_options():
                operations[cleaner_id].append(option_id2)
            continue
        # add the specified option
        if cleaner_id not in operations:
            operations[cleaner_id] = []
        if option_id not in operations[cleaner_id]:
            operations[cleaner_id].append(option_id)
    for (k, v) in operations.items():
        operations[k] = sorted(v)
    return operations
Example #31
0
    def execute(self, cmd, operation_option):
        """Execute or preview the command"""
        ret = None
        try:
            for ret in cmd.execute(self.really_delete):
                if True == ret or isinstance(ret, tuple):
                    # Temporarily pass control to the GTK idle loop,
                    # allow user to abort, and
                    # display progress (if applicable).
                    yield ret
                if self.is_aborted:
                    return
        except SystemExit:
            pass
        except Exception as e:
            # 2 = does not exist
            # 13 = permission denied
            from errno import ENOENT, EACCES
            if isinstance(e, OSError) and e.errno in (ENOENT, EACCES):
                # For access denied, do not show traceback
                exc_message = str(e).decode(FSE)
                logger.error('%s: %s', exc_message, cmd)
            else:
                # For other errors, show the traceback.
                msg = _('Error: {operation_option}: {command}')
                data = {'command': cmd, 'operation_option': operation_option}
                logger.error(msg.format(**data), exc_info=True)
            self.total_errors += 1
        else:
            if ret is None:
                return
            if isinstance(ret['size'], (int, long)):
                size = FileUtilities.bytes_to_human(ret['size'])
                self.size += ret['size']
                self.total_bytes += ret['size']
            else:
                size = "?B"

            if ret['path']:
                path = ret['path']
            else:
                path = ''
            path = path.decode('utf8', 'replace')  # for invalid encoding
            line = u"%s %s %s\n" % (ret['label'], size, path)
            self.total_deleted += ret['n_deleted']
            self.total_special += ret['n_special']
            if ret['label']:
                # the label may be a hidden operation
                # (e.g., win.shell.change.notify)
                self.ui.append_text(line)
Example #32
0
def get_swap_uuid(device):
    """Find the UUID for the swap device"""
    uuid = None
    args = ['blkid', device, '-s', 'UUID']
    (_rc, stdout, _stderr) = General.run_external(args)
    for line in stdout.split('\n'):
        # example: /dev/sda5: UUID="ee0e85f6-6e5c-42b9-902f-776531938bbf"
        ret = re.search("^%s: UUID=\"([a-z0-9-]+)\"" % device, line)
        if ret is not None:
            uuid = ret.group(1)
    logger.debug(
        _("Found UUID for swap file {device} is {uuid}.").format(device=device,
                                                                 uuid=uuid))
    return uuid
Example #33
0
def browse_files(parent, title):
    """Prompt user to select multiple files to delete"""

    if os.name == 'nt' and not os.getenv('BB_NATIVE'):
        return Windows.browse_files(parent, 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(os.path.expanduser('~'))
    resp = chooser.run()
    paths = chooser.get_filenames()
    chooser.destroy()

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

    return paths
Example #34
0
def dnf_clean():
    """Run 'dnf clean all' and return size in bytes recovered"""
    if os.path.exists('/var/run/dnf.pid'):
        msg = _(
            "%s cannot be cleaned because it is currently running.  Close it, and try again.") % "Dnf"
        raise RuntimeError(msg)

    old_size = FileUtilities.getsizedir('/var/cache/dnf')
    args = ['--enablerepo=*', 'clean', 'all']
    invalid = ['You need to be root', 'Cannot remove rpmdb file']
    run_cleaner_cmd('dnf', args, '^unused regex$', invalid)
    new_size = FileUtilities.getsizedir('/var/cache/dnf')

    return old_size - new_size
Example #35
0
 def execute(self, really_delete):
     """Make changes and return results"""
     if FileUtilities.whitelisted(self.path):
         yield whitelist(self.path)
         return
     ret = {
         # TRANSLATORS: This is the label in the log indicating will be
         # deleted (for previews) or was actually deleted
         'label': _('Delete'),
         'n_deleted': 1,
         'n_special': 0,
         'path': self.path,
         'size': FileUtilities.getsize(self.path)
     }
     if really_delete:
         try:
             FileUtilities.delete(self.path, self.shred)
         except WindowsError as e:
             # WindowsError: [Error 32] The process cannot access the file because it is being
             # used by another process: u'C:\\Documents and
             # Settings\\username\\Cookies\\index.dat'
             if 32 != e.winerror and 5 != e.winerror:
                 raise
             try:
                 bleachbit.Windows.delete_locked_file(self.path)
             except:
                 raise
             else:
                 if self.shred:
                     import warnings
                     warnings.warn(
                         _('At least one file was locked by another process, so its contents could not be overwritten. It will be marked for deletion upon system reboot.'
                           ))
                 # TRANSLATORS: The file will be deleted when the
                 # system reboots
                 ret['label'] = _('Mark for deletion')
     yield ret
Example #36
0
def update_dialog(parent, updates):
    """Updates contains the version numbers and URLs"""
    #모듈
    import gtk
    from bleachbit.GuiBasic import open_url
    dlg = gtk.Dialog(title=_("Update BleachBit"),
                     parent=parent,
                     flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
    dlg.set_default_size(250, 125)

    #label에 "A new version is available."을 띄운다.
    label = gtk.Label(_("A new version is available."))
    dlg.vbox.pack_start(label)

    #버전은 update[0], url은 update[1]에 초기화한다.
    for update in updates:
        ver = update[0]
        url = update[1]
        box_update = gtk.HBox()
        # TRANSLATORS: %s expands to version such as '0.8.4' or '0.8.5beta' or
        # similar
        button_stable = gtk.Button(_("Update to version %s") % ver)
        button_stable.connect('clicked',
                              lambda dummy: open_url(url, parent, False))
        button_stable.connect('clicked', lambda dummy: dlg.response(0))
        box_update.pack_start(button_stable, False, padding=10)
        dlg.vbox.pack_start(box_update, False)

    #버튼을 추가한다.
    dlg.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)

    #화면에 뛰우고 작동시킨다.
    dlg.show_all()
    dlg.run()
    dlg.destroy()

    return False
Example #37
0
def wipe_memory():
    """Wipe unallocated memory"""
    # cache the file because 'swapoff' changes it
    proc_swaps = get_proc_swaps()
    devices = disable_swap_linux()
    yield True  # process GTK+ idle loop
    logger.debug(_("Detected these swap devices: %s"), str(devices))
    wipe_swap_linux(devices, proc_swaps)
    yield True
    child_pid = os.fork()
    if 0 == child_pid:
        make_self_oom_target_linux()
        fill_memory_linux()
        sys.exit(0)
    else:
        logger.debug(
            _("The function wipe_memory() with pid %d is waiting for child pid %d."
              ), os.getpid(), child_pid)
        rc = os.waitpid(child_pid, 0)[1]
        if 0 != rc:
            logger.warning(
                _("The child memory-wiping process returned code %d."), rc)
    enable_swap_linux()
    yield 0  # how much disk space was recovered
Example #38
0
    def make_view(self, model, parent, context_menu_event):
        """Create and return a TreeView object"""
        self.view = gtk.TreeView(model)

        # listen for right click (context menu)
        self.view.connect("button_press_event", context_menu_event)

        # first column
        self.renderer0 = gtk.CellRendererText()
        self.column0 = gtk.TreeViewColumn(_("Name"), self.renderer0, text=0)
        self.view.append_column(self.column0)
        self.view.set_search_column(0)

        # second column
        self.renderer1 = gtk.CellRendererToggle()
        self.renderer1.set_property('activatable', True)
        self.renderer1.connect('toggled', self.col1_toggled_cb, model, parent)
        self.column1 = gtk.TreeViewColumn(_("Active"), self.renderer1)
        self.column1.add_attribute(self.renderer1, "active", 1)
        self.view.append_column(self.column1)

        # third column
        self.renderer2 = gtk.CellRendererText()
        if hasattr(self.renderer2, 'set_alignment'):
            # requires PyGTK 2.22
            # http://www.pygtk.org/pygtk2reference/class-gtkcellrenderer.html#method-gtkcellrenderer--set-alignment
            self.renderer2.set_alignment(1.0, 0.0)
        # TRANSLATORS: Size is the label for the column that shows how
        # much space an option would clean or did clean
        self.column2 = gtk.TreeViewColumn(_("Size"), self.renderer2, text=3)
        self.column2.set_alignment(1.0)
        self.view.append_column(self.column2)

        # finish
        self.view.expand_all()
        return self.view
Example #39
0
    def context_menu_event(self, treeview, event):
        """When user right clicks on the tree view"""
        if event.button != 3:
            return False
        pathinfo = treeview.get_path_at_pos(int(event.x), int(event.y))
        if not pathinfo:
            return False
        path, col, _cellx, _celly = pathinfo
        treeview.grab_focus()
        treeview.set_cursor(path, col, 0)
        # context menu applies only to children, not parents
        if len(path) != 2:
            return False
        # find the selected option
        model = treeview.get_model()
        option_id = model[path][2]
        cleaner_id = model[path[0]][2]
        # make a menu
        menu = Gtk.Menu()
        menu.connect('hide', lambda widget: widget.detach())
        # TRANSLATORS: this is the context menu
        preview_item = Gtk.MenuItem(label=_("Preview"))
        preview_item.connect('activate', self.cb_run_option,
                             False, cleaner_id, option_id)
        menu.append(preview_item)
        # TRANSLATORS: this is the context menu
        clean_item = Gtk.MenuItem(label=_("Clean"))
        clean_item.connect('activate', self.cb_run_option,
                           True, cleaner_id, option_id)
        menu.append(clean_item)

        # show the context menu
        menu.attach_to_widget(treeview)
        menu.show_all()
        menu.popup(None, None, None, None, event.button, event.time)
        return True
Example #40
0
    def get_about_dialog(self):
        dialog = Gtk.AboutDialog(comments='Program to clean unnecessary files',
                                 copyright='Copyright (C) 2008-2020 Andrew Ziem',
                                 program_name=APP_NAME,
                                 version=bleachbit.APP_VERSION,
                                 website=bleachbit.APP_URL,
                                 transient_for=self._window)
        try:
            with open(bleachbit.license_filename) as f_license:
                dialog.set_license(f_license.read())
        except (IOError, TypeError):
            dialog.set_license(
                _("GNU General Public License version 3 or later.\nSee https://www.gnu.org/licenses/gpl-3.0.txt"))
        # dialog.set_name(APP_NAME)
        # TRANSLATORS: Maintain the names of translators here.
        # Launchpad does this automatically for translations
        # typed in Launchpad. This is a special string shown
        # in the 'About' box.
        dialog.set_translator_credits(_("translator-credits"))
        if appicon_path and os.path.exists(appicon_path):
            icon = Gtk.Image.new_from_file(appicon_path)
            dialog.set_logo(icon.get_pixbuf())

        return dialog
Example #41
0
    def handle_cleaner_label(self, label):
        """<label> element under <cleaner>
           cleaner태그 아래에 label태그 요소"""

        self.cleaner.name = _(getText(label.childNodes))
        # label객체의 자식노드들을 text로 추출해서 self.cleaner.name에 저장
        translate = label.getAttribute('translate')
        #label에서 translate속성 추출
        if translate and boolstr_to_bool(translate):
            self.xlate_cb(self.cleaner.name)
            # translate 와 translate를 bool값으로 한것이 True면
            # xlate_cb함수에 self.cleaner.name값을 넣어서 사용
            """ xlate_cb함수가 번역과 관련된 함수인데 위에서 xlate_cb의 값이 None이면
                xlate_mode는 False이고이 함수는 None값을 돌려주는 함수가됨 """
            """ xlate_mode의 값이 None이 아니면 xlate_mode가 True가 되는것으로 보아
Example #42
0
def make_self_oom_target_linux():
    """Make the current process the primary target for Linux out-of-memory killer"""
    # In Linux 2.6.36 the system changed from oom_adj to oom_score_adj
    path = '/proc/%d/oom_score_adj' % os.getpid()
    if os.path.exists(path):
        with open(path, 'w') as f:
            f.write('1000')
    else:
        path = '/proc/%d/oomadj' % os.getpid()
        if os.path.exists(path):
            with open(path, 'w') as f:
                f.write('15')
    # OOM likes nice processes
    logger.debug(_("Setting nice value %d for this process."), os.nice(19))
    # OOM prefers non-privileged processes
    try:
        uid = General.getrealuid()
        if uid > 0:
            logger.debug(
                _("Dropping privileges of process ID {pid} to user ID {uid}.").
                format(pid=os.getpid(), uid=uid))
            os.seteuid(uid)
    except:
        logger.exception('Error when dropping privileges')
Example #43
0
    def make_view(self, model, parent, context_menu_event):
        """Create and return a TreeView object"""
        self.view = Gtk.TreeView.new_with_model(model)

        # hide headers
        self.view.set_headers_visible(False)

        # listen for right click (context menu)
        self.view.connect("button_press_event", context_menu_event)

        # first column
        self.renderer0 = Gtk.CellRendererText()
        self.column0 = Gtk.TreeViewColumn(_("Name"), self.renderer0, text=0)
        self.view.append_column(self.column0)
        self.view.set_search_column(0)

        # second column
        self.renderer1 = Gtk.CellRendererToggle()
        self.renderer1.set_property('activatable', True)
        self.renderer1.connect('toggled', self.col1_toggled_cb, model, parent)
        self.column1 = Gtk.TreeViewColumn(_("Active"), self.renderer1)
        self.column1.add_attribute(self.renderer1, "active", 1)
        self.view.append_column(self.column1)

        # third column
        self.renderer2 = Gtk.CellRendererText()
        self.renderer2.set_alignment(1.0, 0.0)
        # TRANSLATORS: Size is the label for the column that shows how
        # much space an option would clean or did clean
        self.column2 = Gtk.TreeViewColumn(_("Size"), self.renderer2, text=3)
        self.column2.set_alignment(1.0)
        self.view.append_column(self.column2)

        # finish
        self.view.expand_all()
        return self.view
Example #44
0
    def cb_wipe_free_space(self, action):
        """callback to wipe free space in arbitrary folder"""
        path = GuiBasic.browse_folder(self.window,
                                      _("Choose a folder"),
                                      multiple=False,
                                      stock_button=gtk.STOCK_OK)
        if not path:
            # user cancelled
            return

        backends['_gui'] = Cleaner.create_wipe_cleaner(path)

        # execute
        operations = {'_gui': ['free_disk_space']}
        self.preview_or_run_operations(True, operations)
Example #45
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.'))
Example #46
0
def make_files_thread(file_count, inspiration, output_folder,
                      delete_when_finished, on_progress):
    if inspiration == 0:
        generated_file_names = generate_2600(file_count,
                                             output_folder,
                                             on_progress=on_progress)
    elif inspiration == 1:
        generated_file_names = generate_emails(file_count,
                                               output_folder,
                                               on_progress=on_progress)
    if delete_when_finished:
        on_progress(0, msg=_('Deleting files'))
        for i in range(0, file_count):
            os.unlink(generated_file_names[i])
            on_progress(1.0 * (i + 1) / file_count)
    on_progress(1.0, is_done=True)
Example #47
0
    def _make_dialog(self, parent):
        """Make the main dialog"""
        Gtk.Dialog.__init__(self, _("Make chaff"), parent)
        self.set_border_width(5)
        box = self.get_content_area()

        label = Gtk.Label(
            _("Make randomly-generated messages derived from Hillary Clinton's emails."))
        box.add(label)

        spin_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        spin_box.add(Gtk.Label(_("Number of files")))
        adjustment = Gtk.Adjustment(100, 1, 99999, 1, 1000, 0)
        self.file_count = Gtk.SpinButton(adjustment=adjustment)
        spin_box.add(self.file_count)
        box.add(spin_box)

        folder_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        folder_box.add(Gtk.Label(_("Select destination folder")))
        self.choose_folder_button = Gtk.FileChooserButton()
        self.choose_folder_button.set_action(
            Gtk.FileChooserAction.SELECT_FOLDER)
        import tempfile
        self.choose_folder_button.set_filename(tempfile.gettempdir())
        folder_box.add(self.choose_folder_button)
        box.add(folder_box)

        delete_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        delete_box.add(Gtk.Label(_("When finished")))
        self.when_finished_combo = Gtk.ComboBoxText()
        self.combo_options = (
            _('Delete without shredding'), _('Do not delete'))
        for combo_option in self.combo_options:
            self.when_finished_combo.append_text(combo_option)
        self.when_finished_combo.set_active(0)  # Set default
        delete_box.add(self.when_finished_combo)
        box.add(delete_box)

        self.progressbar = Gtk.ProgressBar()
        box.add(self.progressbar)
        self.progressbar.hide()

        self.make_button = Gtk.Button(_("Make files"))
        self.make_button.connect('clicked', self.on_make_files)
        box.add(self.make_button)
Example #48
0
    def run_deep_scan(self):
        """Run deep scans"""
        logger.debug(' deepscans=%s' % self.deepscans)
        # TRANSLATORS: The "deep scan" feature searches over broad
        # areas of the file system such as the user's whole home directory
        # or all the system executables.
        self.ui.update_progress_bar(_("Please wait.  Running deep scan."))
        yield True  # allow GTK to update the screen
        ds = DeepScan.DeepScan(self.deepscans)

        for cmd in ds.scan():
            if True == cmd:
                yield True
                continue
            for ret in self.execute(cmd, 'deepscan'):
                yield True
Example #49
0
 def get_diagnostics_dialog(self):
     """Show diagnostic information"""
     dialog = Gtk.Dialog(_("System information"), self._window)
     dialog.set_default_size(600, 400)
     txtbuffer = Gtk.TextBuffer()
     from bleachbit import Diagnostic
     txt = Diagnostic.diagnostic_info()
     txtbuffer.set_text(txt)
     textview = Gtk.TextView.new_with_buffer(txtbuffer)
     textview.set_editable(False)
     swindow = Gtk.ScrolledWindow()
     swindow.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
     swindow.add(textview)
     dialog.vbox.pack_start(swindow, True, True, 0)
     dialog.add_buttons(Gtk.STOCK_COPY, 100,
                        Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
     return (dialog, txt)
Example #50
0
def check_updates(check_beta, check_winapp2, append_text, cb_success):
    """Check for updates via the Internet"""
    opener = build_opener()
    socket.setdefaulttimeout(bleachbit.socket_timeout)
    opener.addheaders = [('User-Agent', user_agent())]
    import encodings.idna  # https://github.com/bleachbit/bleachbit/issues/760
    try:
        handle = opener.open(bleachbit.update_check_url)
    except URLError as e:
        logger.error(
            _('Error when opening a network connection to check for updates. Please verify the network is working and that a firewall is not blocking this application. Error message: {}'
              ).format(e))
        return ()
    doc = handle.read()
    try:
        dom = xml.dom.minidom.parseString(doc)
    except:
        logger.exception('The update information does not parse: %s', doc)
        return ()

    def parse_updates(element):
        if element:
            ver = element[0].getAttribute('ver')
            url = element[0].firstChild.data
            return ver, url
        return ()

    stable = parse_updates(dom.getElementsByTagName("stable"))
    beta = parse_updates(dom.getElementsByTagName("beta"))

    wa_element = dom.getElementsByTagName('winapp2')
    if check_winapp2 and wa_element:
        wa_sha512 = wa_element[0].getAttribute('sha512')
        wa_url = wa_element[0].getAttribute('url')
        update_winapp2(wa_url, wa_sha512, append_text, cb_success)

    dom.unlink()

    if stable and beta and check_beta:
        return stable, beta
    if stable:
        return stable,
    if beta and check_beta:
        return beta,
    return ()
Example #51
0
def update_winapp2(url, hash_expected, append_text, cb_success):
    """Download latest winapp2.ini file.  Hash is sha512 or None to disable checks"""
    # first, determine whether an update is necessary
    #먼저 업데이트가 필요한지 여부를 확인합니다.
    #bleachbit모듈에서 personal_cleaners_dir을 가져온다.
    from bleachbit import personal_cleaners_dir
    #fn은 personal_cleaners_dir의 'winapp2.ini'이다.
    fn = os.path.join(personal_cleaners_dir, 'winapp2.ini')
    delete_current = False
    if os.path.exists(fn):
        #파일을 읽기모드로 연다.
        f = open(fn, 'r')
        hash_current = hashlib.sha512(f.read()).hexdigest()
        if not hash_expected or hash_current == hash_expected:
            # update is same as current
            #업데이트가 현재 업데이트와 동일하면 return한다.
            return
        #파일을 닫는다.
        f.close()
        delete_current = True
    # download update
    # 업데이트를 다운로드한다.
    opener = build_opener()
    opener.addheaders = [('User-Agent', user_agent())]
    doc = opener.open(fullurl=url, timeout=20).read()
    # verify hash
    #해시를 확인한다.
    hash_actual = hashlib.sha512(doc).hexdigest()
    #hash_expected이고 hash_actual이 아니면 hash_expected이다.
    if hash_expected and not hash_actual == hash_expected:
        raise RuntimeError("hash for %s actually %s instead of %s" %
                           (url, hash_actual, hash_expected))
    # delete current
    # current를 삭제한다.
    if delete_current:
        from bleachbit.FileUtilities import delete
        delete(fn, True)
    # write file
    # 파일을 쓰기모드로 열고 'New winapp2.ini was downloaded.'에 추가한다.
    if not os.path.exists(personal_cleaners_dir):
        os.mkdir(personal_cleaners_dir)
    f = open(fn, 'w')
    f.write(doc)
    append_text(_('New winapp2.ini was downloaded.'))
    cb_success()
Example #52
0
    def execute(self, really_delete):
        """Make changes and return results"""

        if FileUtilities.whitelisted(self.path):
            yield whitelist(self.path)
            return

        ret = {
            # TRANSLATORS: The file will be truncated to 0 bytes in length
            'label': _('Truncate'),
            'n_deleted': 1,
            'n_special': 0,
            'path': self.path,
            'size': FileUtilities.getsize(self.path)}
        if really_delete:
            f = open(self.path, 'wb')
            f.truncate(0)
        yield ret
Example #53
0
 def get_walk_all(top):
     """Delete files and directories inside a directory but not the top directory"""
     for expanded in glob.iglob(top):
         path = None  # sentinel value
         for path in FileUtilities.children_in_directory(
                 expanded, True):
             yield path
         # This condition executes when there are zero iterations
         # in the loop above.
         if path is None:
             # This is a lint checker because this scenario may
             # indicate the cleaner developer made a mistake.
             if os.path.isfile(expanded):
                 logger.debug(
                     _('search="walk.all" used with regular file path="%s"'
                       ),
                     expanded,
                 )
Example #54
0
    def execute(self, really_delete):
        """Make changes and return results"""

        if FileUtilities.whitelisted(self.path):
            yield whitelist(self.path)
            return

        ret = {
            'label': _('Clean file'),
            'n_deleted': 0,
            'n_special': 1,
            'path': self.path,
            'size': None}
        if really_delete:
            oldsize = FileUtilities.getsize(self.path)
            FileUtilities.clean_json(self.path, self.address)
            newsize = FileUtilities.getsize(self.path)
            ret['size'] = oldsize - newsize
        yield ret
Example #55
0
 def __flush(self):
     """Write information to disk"""
     if not self.purged:
         self.__purge()
     if not os.path.exists(bleachbit.options_dir):
         General.makedirs(bleachbit.options_dir)
     mkfile = not os.path.exists(bleachbit.options_file)
     with open(bleachbit.options_file, 'w', encoding='utf-8-sig') as _file:
         try:
             self.config.write(_file)
         except IOError as e:
             from errno import ENOSPC
             if e.errno == ENOSPC:
                 logger.error(
                     _("Disk was full when writing configuration to file %s"), bleachbit.options_file)
             else:
                 raise
     if mkfile and General.sudo_mode():
         General.chownself(bleachbit.options_file)
Example #56
0
 def get_walk_all(top):
     """Delete files and directories inside a directory but not the top directory"""
     for expanded in glob.iglob(top):
         path = None  # sentinel value
         yield from FileUtilities.children_in_directory(expanded, True)
         # This condition executes when there are zero iterations
         # in the loop above.
         if path is None:
             # This is a lint checker because this scenario may
             # indicate the cleaner developer made a mistake.
             if os.path.isfile(expanded):
                 logger.debug(
                     # TRANSLATORS: This is a lint-style warning that there seems to be a
                     # mild mistake in the CleanerML file because walk.all is expected to
                     # be used with directories instead of with files.
                     _('search="walk.all" used with regular file path="%s"'
                       ),
                     expanded,
                 )
Example #57
0
def list_cleanerml_files(local_only=False):
    """List CleanerML files"""
    cleanerdirs = (bleachbit.personal_cleaners_dir, )
    if bleachbit.local_cleaners_dir:
        # If the application is installed, locale_cleaners_dir is None
        cleanerdirs = (bleachbit.local_cleaners_dir, )
    if not local_only and bleachbit.system_cleaners_dir:
        cleanerdirs += (bleachbit.system_cleaners_dir, )
    for pathname in listdir(cleanerdirs):
        if not pathname.lower().endswith('.xml'):
            continue
        import stat
        st = os.stat(pathname)
        if sys.platform != 'win32' and stat.S_IMODE(st[stat.ST_MODE]) & 2:
            logger.warning(
                _("Ignoring cleaner because it is world writable: %s"),
                pathname)
            continue
        yield pathname
Example #58
0
def create_pot():
    """Create a .pot for translation using gettext"""

    f = open('../po/cleanerml.pot', 'w')

    for pathname in listdir('../cleaners'):
        if not pathname.lower().endswith(".xml"):
            continue
        strings = []
        try:
            CleanerML(pathname,
                      lambda newstr, translators=None: strings.append(
                          [newstr, translators]))
        except:
            logger.exception(_("Error reading cleaner: %s"), pathname)
            continue
        for (string, translators) in strings:
            f.write(pot_fragment(string, pathname, translators))

    f.close()
Example #59
0
    def get_commands(self):

        def run_process():
            try:
                if self.wait:
                    args = self.cmd.split(' ')
                    (rc, stdout, stderr) = General.run_external(args)
                else:
                    rc = 0  # unknown because we don't wait
                    from subprocess import Popen
                    Popen(self.cmd)
            except Exception as e:
                raise RuntimeError(
                    'Exception in external command\nCommand: %s\nError: %s' % (self.cmd, str(e)))
            else:
                if not 0 == rc:
                    logger.warning('Command: %s\nReturn code: %d\nStdout: %s\nStderr: %s\n',
                                   self.cmd, rc, stdout, stderr)
            return 0
        yield Command.Function(path=None, func=run_process, label=_("Run external command: %s") % self.cmd)
Example #60
0
def disable_swap_linux():
    """Disable Linux swap and return list of devices"""
    if 0 == count_swap_linux():
        return
    logger.debug(_("Disabling swap."))
    args = ["swapoff", "-a", "-v"]
    (rc, stdout, stderr) = General.run_external(args)
    if 0 != rc:
        raise RuntimeError(stderr.replace("\n", ""))
    devices = []
    for line in stdout.split('\n'):
        line = line.replace('\n', '')
        if '' == line:
            continue
        ret = parse_swapoff(line)
        if ret is None:
            raise RuntimeError("Unexpected output:\nargs='%(args)s'\nstdout='%(stdout)s'\nstderr='%(stderr)s'"
                               % {'args': str(args), 'stdout': stdout, 'stderr': stderr})
        devices.append(ret)
    return devices