• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bleachbit / bleachbit / 23113774427

15 Mar 2026 03:49PM UTC coverage: 73.163% (+2.0%) from 71.208%
23113774427

push

github

az0
Merge branch 'dev4'

654 of 873 new or added lines in 32 files covered. (74.91%)

15 existing lines in 11 files now uncovered.

7028 of 9606 relevant lines covered (73.16%)

0.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.29
/bleachbit/Update.py
1
# vim: ts=4:sw=4:expandtab
2

3
# BleachBit
4
# Copyright (C) 2008-2025 Andrew Ziem
5
# https://www.bleachbit.org
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19

20

21
"""
22
Check for updates via the Internet
23
"""
24

25
# standard library
26
import hashlib
1✔
27
import logging
1✔
28
import os
1✔
29
import sys
1✔
30
import xml.dom.minidom
1✔
31

32
# third-party
33
import requests
1✔
34

35
# local
36
import bleachbit
1✔
37
from bleachbit.Language import get_text as _
1✔
38
from bleachbit.Network import (download_url_to_fn, fetch_url,
1✔
39
                               get_ip_for_url, get_update_request_headers)
40

41

42
logger = logging.getLogger(__name__)
1✔
43

44

45
def update_winapp2(url, hash_expected, append_text, cb_success):
1✔
46
    """Download latest winapp2.ini file.  Hash is sha512 or None to disable checks"""
47
    # first, determine whether an update is necessary
48

49
    fn = os.path.join(bleachbit.personal_cleaners_dir, 'winapp2.ini')
1✔
50
    if os.path.exists(fn):
1✔
51
        with open(fn, 'rb') as f:
1✔
52
            hash_current = hashlib.sha512(f.read()).hexdigest()
1✔
53
            if not hash_expected or hash_current == hash_expected:
1✔
54
                # update is same as current
55
                return
1✔
56
    # download update
57
    # Define error handler to propagate download errors
58

59
    def on_error(msg, msg2):
1✔
60
        raise RuntimeError(f"{msg}: {msg2}")
1✔
61

62
    if download_url_to_fn(url, fn, hash_expected, on_error):
1✔
63
        append_text(_('New winapp2.ini was downloaded.'))
1✔
64
        cb_success()
1✔
65

66

67
def update_dialog(parent, updates):
1✔
68
    """Updates contains the version numbers and URLs"""
69
    # import these here to allow headless mode.
NEW
70
    from bleachbit.GtkShim import Gtk  # pylint: disable=import-outside-toplevel
×
71
    from bleachbit.GuiBasic import open_url  # pylint: disable=import-outside-toplevel
×
72
    dlg = Gtk.Dialog(title=_("Update BleachBit"),
×
73
                     transient_for=parent,
74
                     modal=True,
75
                     destroy_with_parent=True)
76
    dlg.set_default_size(250, 125)
×
77

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

81
    for (ver, url) in updates:
×
82
        box_update = Gtk.Box()
×
83
        # TRANSLATORS: %s expands to version such as '4.6.0'
84
        button_stable = Gtk.Button(_("Update to version %s") % ver)
×
85
        button_stable.connect(
×
86
            'clicked', lambda dummy: open_url(url, parent, False))
87
        button_stable.connect('clicked', lambda dummy: dlg.response(0))
×
88
        box_update.pack_start(button_stable, False, True, 10)
×
89
        dlg.vbox.pack_start(box_update, False, True, 0)
×
90

91
    dlg.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
×
92

93
    dlg.show_all()
×
94
    dlg.run()
×
95
    dlg.destroy()
×
96

97
    return False
×
98

99

100
def check_updates(check_beta, check_winapp2, append_text, cb_success):
1✔
101
    """Check for updates via the Internet"""
102
    url = bleachbit.update_check_url
1✔
103
    if 'windowsapp' in sys.executable.lower():
1✔
104
        url += '?windowsapp=1'
×
105
    try:
1✔
106
        response = fetch_url(url,
1✔
107
                             headers=get_update_request_headers())
108
    except requests.RequestException as e:
1✔
109
        logger.error(
1✔
110
            _('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))
111
        logger.debug('URL %s has IP address %s', url, get_ip_for_url(url))
1✔
112
        if hasattr(e, 'response') and e.response is not None:
1✔
113
            logger.debug(e.response.headers)
×
114
        return ()
1✔
115
    try:
1✔
116
        dom = xml.dom.minidom.parseString(response.text)
1✔
117
    except:
×
118
        logger.exception(
×
119
            'The update information does not parse: %s', response.text)
120
        return ()
×
121

122
    def parse_updates(element):
1✔
123
        if element:
1✔
124
            ver = element[0].getAttribute('ver')
1✔
125
            url = element[0].firstChild.data
1✔
126
            assert isinstance(ver, str)
1✔
127
            assert isinstance(url, str)
1✔
128
            assert url.startswith('http')
1✔
129
            return ver, url
1✔
130
        return ()
1✔
131

132
    stable = parse_updates(dom.getElementsByTagName("stable"))
1✔
133
    beta = parse_updates(dom.getElementsByTagName("beta"))
1✔
134

135
    wa_element = dom.getElementsByTagName('winapp2')
1✔
136
    if check_winapp2 and wa_element:
1✔
137
        wa_sha512 = wa_element[0].getAttribute('sha512')
×
138
        wa_url = wa_element[0].getAttribute('url')
×
139
        update_winapp2(wa_url, wa_sha512, append_text, cb_success)
×
140

141
    dom.unlink()
1✔
142

143
    if stable and beta and check_beta:
1✔
144
        return (stable, beta)
1✔
145
    if stable:
1✔
146
        return (stable,)
1✔
147
    if beta and check_beta:
1✔
148
        return (beta,)
1✔
149
    return ()
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc