This file is indexed.

/usr/lib/python2.7/dist-packages/quodlibet/update.py is in exfalso 3.7.1-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# -*- coding: utf-8 -*-
# Copyright 2016 Christoph Reiter
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.

"""Check for new versions of the application

For each "build type" (basically each bundle/installer) we host
an (sparkle appcast) rss feed on quodlibet.github.io.
We download it and compare versions...

Since there can be multiple builds per release for the same release type
(e.g. the installer was broken and had to be redone) the build version
is used and not the release version.
"""

from gi.repository import Gtk

import quodlibet
from quodlibet.build import BUILD_TYPE
from quodlibet.compat import text_type, urlopen
from quodlibet.qltk.window import Dialog
from quodlibet.util.dprint import print_exc
from quodlibet.util import escape
from quodlibet.util.thread import call_async, Cancellable


class UpdateError(Exception):
    pass


def parse_version(version_string):
    """Might raise ValueError"""

    return tuple(map(int, version_string.split(".")))


def format_version(version_tuple):
    return u".".join(map(text_type, version_tuple))


def fetch_versions(build_type, timeout=5.0):
    """Fetches the list of available releases and returns a list
    of version tuples. Sorted and oldest version first. The list
    might be empty. Also returns an URL to the download page.

    Args:
        build_type (text): the build type. e.g. "default" or "windows"
        timeout (float): timeout in seconds

    Thread safe.

    Raises UpdateError
    """

    # TODO: we currently don't depend on feedparser.. maybe we should?
    try:
        import feedparser
    except ImportError as error:
        raise UpdateError(error)

    try:
        content = urlopen(
            u"https://quodlibet.github.io/appcast/%s.rss" % build_type,
            timeout=timeout).read()
    except Exception as error:
        raise UpdateError(error)

    d = feedparser.parse(content)
    if d.bozo:
        raise UpdateError(d.bozo_exception)

    try:
        link = d.feed.link
        enclosures = [e for entry in d.entries for e in entry.enclosures]
    except AttributeError as error:
        raise UpdateError(error)

    try:
        versions = [parse_version(en.version) for en in enclosures]
    except ValueError as error:
        raise UpdateError(error)

    return sorted(versions), link


class UpdateDialog(Dialog):

    def __init__(self, parent):
        super(UpdateDialog, self).__init__(
            title=_("Checking for Updates"), use_header_bar=True,
            modal=True)

        self.set_default_size(380, 110)
        self.set_transient_for(parent)
        self.add_button(_("_Cancel"), Gtk.ResponseType.CANCEL)
        self.set_default_response(Gtk.ResponseType.CANCEL)

        content = self.get_content_area()
        self._stack = Gtk.Stack(border_width=10)
        self._stack.set_transition_duration(500)
        self._stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
        content.pack_start(self._stack, True, True, 0)
        content.show_all()

        spinner = Gtk.Spinner()
        spinner.start()
        self._set_widget(spinner)

    def run(self):
        def do_fetch_versions():
            try:
                return fetch_versions(BUILD_TYPE)
            except UpdateError:
                print_exc()
                return None

        cancel = Cancellable()
        self.connect("response", self._on_response, cancel)
        call_async(do_fetch_versions, cancel, self._on_result)

        return super(UpdateDialog, self).run()

    def _on_result(self, args):
        if args is None or not args[0]:
            text = _("Connection failed")
        else:
            versions, url = args
            version = quodlibet.get_build_version()

            def f(v):
                return "<b>%s</b>" % escape(format_version(v))

            if version >= versions[-1]:
                text = (_("You are already using the newest version "
                          "%(version)s") % {"version": f(version)})
            else:
                text = (_("A new version %(new-version)s is available\n\n"
                          "You are currently using version %(old-version)s\n\n"
                          "Visit the <a href='%(url)s'>website</a>") % {
                            "new-version": f(versions[-1]),
                            "old-version": f(version),
                            "url": escape(url)})

        self._set_widget(
            Gtk.Label(label=text, use_markup=True, wrap=True,
                      justify=Gtk.Justification.CENTER))

    def _set_widget(self, widget):
        old = self._stack.get_visible_child()
        self._stack.add(widget)
        widget.show()
        self._stack.set_visible_child(widget)
        if old:
            old.destroy()

    def _on_response(self, dialog, response_id, cancel):
        cancel.cancel()