Пример #1
0
 def fetch(self, fetcher, progress):
     path = os.path.join(sysconf.get("deb-root", "/"),
                         "var/lib/dpkg/status")
     digest = os.path.getmtime(path)
     if digest == self._digest:
         return True
     self.removeLoaders()
     loader = DebTagFileLoader(path)
     loader.setInstalled(True)
     loader.setChannel(self)
     self._loaders.append(loader)
     self._digest = digest
     return True
Пример #2
0
 def fetch(self, fetcher, progress):
     path = os.path.join(sysconf.get("deb-root", "/"),
                         sysconf.get("deb-admindir", "var/lib/dpkg"),
                         "status")
     digest = os.path.getmtime(path)
     if digest == self._digest:
         return True
     self.removeLoaders()
     filelistspath = os.path.join(sysconf.get("deb-root", "/"),
                         sysconf.get("deb-admindir", "var/lib/dpkg"),
                         "info")
     changelogpath = os.path.join(sysconf.get("deb-root", "/"),
                         "usr/share/doc")
     loader = DebTagFileLoader(path, None, filelistspath, changelogpath)
     loader.setInstalled(True)
     loader.setChannel(self)
     self._loaders.append(loader)
     self._digest = digest
     return True
Пример #3
0
class APTDEBChannel(PackageChannel):
    def __init__(self, baseurl, distro, comps, fingerprint, *args):
        super(APTDEBChannel, self).__init__(*args)

        self._baseurl = baseurl
        self._distro = distro
        self._comps = comps
        if fingerprint:
            self._fingerprint = "".join(
                [x for x in fingerprint if not x.isspace()])
        else:
            self._fingerprint = None

    def _getURL(self, filename="", component=None, subpath=False):
        if subpath:
            distrourl = ""
        else:
            distrourl = posixpath.join(self._baseurl, "dists", self._distro)
        if component:
            return posixpath.join(distrourl, component, "binary-" + DEBARCH,
                                  filename)
        else:
            return posixpath.join(distrourl, filename)

    def getCacheCompareURLs(self):
        return [self._getURL("Release")]

    def getFetchSteps(self):
        # Release files are not being used
        #return len(self._comps)*2+2
        return len(self._comps) + 2

    def fetch(self, fetcher, progress):

        fetcher.reset()

        # Fetch release file
        item = fetcher.enqueue(self._getURL("Release"))
        gpgitem = fetcher.enqueue(self._getURL("Release.gpg"))
        fetcher.run(progress=progress)
        failed = item.getFailedReason()
        if failed:
            progress.add(self.getFetchSteps() - 2)
            progress.show()
            if fetcher.getCaching() is NEVER:
                lines = [
                    _("Failed acquiring information for '%s':") % self,
                    u"%s: %s" % (item.getURL(), failed)
                ]
                raise Error, "\n".join(lines)
            return False

        digest = getFileDigest(item.getTargetPath())
        if digest == self._digest:
            progress.add(self.getFetchSteps() - 2)
            progress.show()
            return True
        self.removeLoaders()

        # Parse release file
        md5sum = {}
        insidemd5sum = False
        for line in open(item.getTargetPath()):
            if not insidemd5sum:
                if line.startswith("MD5Sum:"):
                    insidemd5sum = True
            elif not line.startswith(" "):
                insidemd5sum = False
            else:
                try:
                    md5, size, path = line.split()
                except ValueError:
                    pass
                else:
                    md5sum[path] = (md5, int(size))

        if self._fingerprint:
            try:
                failed = gpgitem.getFailedReason()
                if failed:
                    raise Error, _(
                        "Channel '%s' has fingerprint but download "
                        "of Release.gpg failed: %s") % (self, failed)

                status, output = commands.getstatusoutput(
                    "gpg --batch --no-secmem-warning --status-fd 1 "
                    "--verify %s %s" %
                    (gpgitem.getTargetPath(), item.getTargetPath()))

                badsig = False
                goodsig = False
                validsig = None
                for line in output.splitlines():
                    if line.startswith("[GNUPG:]"):
                        tokens = line[8:].split()
                        first = tokens[0]
                        if first == "VALIDSIG":
                            validsig = tokens[1]
                        elif first == "GOODSIG":
                            goodsig = True
                        elif first == "BADSIG":
                            badsig = True
                if badsig:
                    raise Error, _("Channel '%s' has bad signature") % self
                if not goodsig or validsig != self._fingerprint:
                    raise Error, _("Channel '%s' signed with unknown key") \
                                 % self
            except Error, e:
                progress.add(self.getFetchSteps() - 2)
                progress.show()
                if fetcher.getCaching() is NEVER:
                    raise
                else:
                    return False

        # Fetch component package lists and release files
        fetcher.reset()
        pkgitems = []
        #relitems = []
        for comp in self._comps:
            packages = self._getURL("Packages", comp, subpath=True)
            url = self._getURL("Packages", comp)
            if packages + ".bz2" in md5sum:
                upackages = packages
                packages += ".bz2"
                url += ".bz2"
            elif packages + ".gz" in md5sum:
                upackages = packages
                packages += ".gz"
                url += ".gz"
            elif packages not in md5sum:
                iface.warning(
                    _("Component '%s' is not in Release file "
                      "for channel '%s'") % (comp, self))
                continue
            else:
                upackages = None
            info = {"component": comp, "uncomp": True}
            info["md5"], info["size"] = md5sum[packages]
            if upackages:
                info["uncomp_md5"], info["uncomp_size"] = md5sum[upackages]
            pkgitems.append(fetcher.enqueue(url, **info))

            #release = self._getURL("Release", comp, subpath=True)
            #if release in md5sum:
            #    url = self._getURL("Release", comp)
            #    info = {"component": comp}
            #    info["md5"], info["size"] = md5sum[release]
            #    relitems.append(fetcher.enqueue(url, **info))
            #else:
            #    progress.add(1)
            #    progress.show()
            #    relitems.append(None)

        fetcher.run(progress=progress)

        errorlines = []
        for i in range(len(pkgitems)):
            pkgitem = pkgitems[i]
            #relitem = relitems[i]
            if pkgitem.getStatus() == SUCCEEDED:
                # Release files for components are not being used.
                #if relitem and relitem.getStatus() == SUCCEEDED:
                #    try:
                #        for line in open(relitem.getTargetPath()):
                #            if line.startswith("..."):
                #                pass
                #    except (IOError, ValueError):
                #        pass
                localpath = pkgitem.getTargetPath()
                loader = DebTagFileLoader(localpath, self._baseurl)
                loader.setChannel(self)
                self._loaders.append(loader)
            else:
                errorlines.append(
                    u"%s: %s" % (pkgitem.getURL(), pkgitem.getFailedReason()))

        if errorlines:
            if fetcher.getCaching() is NEVER:
                errorlines.insert(
                    0,
                    _("Failed acquiring information for '%s':") % self)
                raise Error, "\n".join(errorlines)
            return False

        self._digest = digest

        return True
Пример #4
0
class APTDEBChannel(PackageChannel):

    # It's important for the default to be here so that old pickled
    # instances which don't have these attributes still work fine.
    _fingerprint = None
    _keyring = None
    _trustdb = None
    _arch = None

    def __init__(self, baseurl, distro, comps, fingerprint, keyring, trustdb,
                 *args):
        super(APTDEBChannel, self).__init__(*args)

        distro = distro.lstrip('/')
        self._baseurl = baseurl
        self._distro = distro
        self._comps = comps
        if fingerprint:
            self._fingerprint = "".join(fingerprint.split())
        if keyring:
            self._keyring = keyring
        if trustdb:
            self._trustdb = trustdb

    def _getURL(self, filename="", component=None, subpath=False):
        if self._arch is None:
            self._arch = getArchitecture()
        if subpath:
            distrourl = ""
        elif not self._comps:
            distrourl = posixpath.join(self._baseurl, self._distro)
        else:
            distrourl = posixpath.join(self._baseurl, "dists", self._distro)
        if component:
            return posixpath.join(distrourl, component, "binary-" + self._arch,
                                  filename)
        else:
            return posixpath.join(distrourl, filename)

    def getCacheCompareURLs(self):
        return [self._getURL("Release")]

    def getFetchSteps(self):
        if self._comps:
            # Packages*components + Release + Release.gpg
            return len(self._comps) + 2
            # Component Release files are not being used, otherwise it'd be:
            # (Packages+Release)*components + Release + Release.gpg
            #return len(self._comps)*2+2
        else:
            # Packages + Release + Release.gpg
            return 3

    def _checkRelease(self, release_item, release_gpg_item):
        is_secure_channel = bool(self._fingerprint or self._keyring)
        need_release = bool(is_secure_channel or self._comps)
        release_failed = release_item.getFailedReason()

        if need_release and release_failed:
            raise Error, _("Download of Release failed for channel '%s': %s") \
                         % (self, release_failed)

        if is_secure_channel:
            release_gpg_failed = release_gpg_item.getFailedReason()
            if release_gpg_failed:
                raise Error, \
                      _("Download of Release.gpg failed for secure "
                        "channel '%s': %s") % (self, release_gpg_failed)

            arguments = [
                "gpg", "--batch", "--no-secmem-warning", "--status-fd", "1"
            ]

            if self._keyring:
                arguments.append("--no-default-keyring")
                if os.path.isfile(self._keyring):
                    arguments.extend(["--keyring", self._keyring])
                elif os.path.isdir(self._keyring):
                    for keyring in next(os.walk(self._keyring))[2]:
                        keyring = os.path.join(self._keyring, keyring)
                        arguments.extend(["--keyring", keyring])

            if self._trustdb:
                arguments.extend(["--trustdb-name", self._trustdb])

            arguments.extend([
                "--verify",
                release_gpg_item.getTargetPath(),
                release_item.getTargetPath()
            ])

            command = " ".join(arguments)
            status, output = commands.getstatusoutput(command)

            badsig = False
            goodsig = False
            validsig = None
            for line in output.splitlines():
                if line.startswith("[GNUPG:]"):
                    tokens = line[8:].split()
                    first = tokens[0]
                    if first == "VALIDSIG":
                        validsig = tokens[1]
                    elif first == "GOODSIG":
                        goodsig = True
                    elif first == "BADSIG":
                        badsig = True
            if badsig:
                raise Error, _("Channel '%s' has bad signature") % self
            if (not goodsig
                    or (self._fingerprint and validsig != self._fingerprint)):
                raise Error, _("Channel '%s' signed with unknown key") % self

    def _parseRelease(self, release_item):
        checksum = {}
        insidemd5sum = False
        insidesha1 = False
        insidesha256 = False
        for line in open(release_item.getTargetPath()):
            if not insidemd5sum:
                if line.startswith("MD5Sum:"):
                    insidemd5sum = True
            elif not line.startswith(" "):
                insidemd5sum = False
            elif insidemd5sum:
                try:
                    md5, size, path = line.split()
                except ValueError:
                    pass
                else:
                    if not path in checksum:
                        checksum[path] = {}
                    checksum[path]["md5"] = md5
                    checksum[path]["size"] = int(size)
            if not insidesha1:
                if line.startswith("SHA1:"):
                    insidesha1 = True
            elif not line.startswith(" "):
                insidesha1 = False
            elif insidesha1:
                try:
                    sha1, size, path = line.split()
                except ValueError:
                    pass
                else:
                    if not path in checksum:
                        checksum[path] = {}
                    checksum[path]["sha1"] = sha1
                    checksum[path]["size"] = int(size)
            if not insidesha256:
                if line.startswith("SHA256:"):
                    insidesha256 = True
            elif not line.startswith(" "):
                insidesha256 = False
            elif insidesha256:
                try:
                    sha256, size, path = line.split()
                except ValueError:
                    pass
                else:
                    if not path in checksum:
                        checksum[path] = {}
                    checksum[path]["sha256"] = sha256
                    checksum[path]["size"] = int(size)
        return checksum

    def _enqueuePackages(self, fetcher, checksum=None, component=None):
        info = {}
        url = self._getURL("Packages", component)
        subpath = self._getURL("Packages", component, subpath=True)
        if checksum is not None:
            if subpath + ".lzma" in checksum:
                compressed_subpath = subpath + ".lzma"
                url += ".lzma"
            elif subpath + ".bz2" in checksum:
                compressed_subpath = subpath + ".bz2"
                url += ".bz2"
            elif subpath + ".gz" in checksum:
                compressed_subpath = subpath + ".gz"
                url += ".gz"
            elif subpath in checksum:
                compressed_subpath = None
            else:
                return None
            if compressed_subpath:
                info["uncomp"] = True
                info["md5"] = checksum[compressed_subpath].get("md5", None)
                info["sha1"] = checksum[compressed_subpath].get("sha1", None)
                info["sha256"] = checksum[compressed_subpath].get(
                    "sha256", None)
                info["size"] = checksum[compressed_subpath]["size"]
                if subpath in checksum:
                    info["uncomp_md5"] = checksum[subpath].get("md5", None)
                    info["uncomp_sha1"] = checksum[subpath].get("sha1", None)
                    info["uncomp_sha256"] = checksum[subpath].get(
                        "sha256", None)
                    info["uncomp_size"] = checksum[subpath]["size"]
            else:
                info["md5"] = checksum[subpath].get("md5", None)
                info["sha1"] = checksum[subpath].get("sha1", None)
                info["sha256"] = checksum[subpath].get("sha256", None)
                info["size"] = checksum[subpath]["size"]
        else:
            # Default to Packages.gz when we can't find out.
            info["uncomp"] = True
            url += ".gz"
        return fetcher.enqueue(url, **info)

    def fetch(self, fetcher, progress):

        fetcher.reset()

        # Fetch release file
        release_item = fetcher.enqueue(self._getURL("Release"))
        release_gpg_item = fetcher.enqueue(self._getURL("Release.gpg"))
        fetcher.run(progress=progress)

        try:
            self._checkRelease(release_item, release_gpg_item)
        except Error, e:
            progress.add(self.getFetchSteps() - 2)
            progress.show()
            if fetcher.getCaching() is NEVER:
                raise
            else:
                return False

        if not release_item.getFailedReason():
            digest = getFileDigest(release_item.getTargetPath())
            if digest == self._digest:
                progress.add(self.getFetchSteps() - 2)
                progress.show()
                return True
            self.removeLoaders()
            checksum = self._parseRelease(release_item)
        else:
            digest = None
            checksum = None

        fetcher.reset()

        if not self._comps:
            packages_items = [self._enqueuePackages(fetcher, checksum)]
        else:
            packages_items = []
            for component in self._comps:
                item = self._enqueuePackages(fetcher, checksum, component)
                if item:
                    packages_items.append(item)
                else:
                    iface.warning(
                        _("Component '%s' is not in Release file "
                          "for channel '%s'") % (component, self))

        fetcher.run(progress=progress)

        errorlines = []
        for item in packages_items:
            if item.getStatus() == SUCCEEDED:
                localpath = item.getTargetPath()
                loader = DebTagFileLoader(localpath, self._baseurl)
                loader.setChannel(self)
                self._loaders.append(loader)
            else:
                errorlines.append(u"%s: %s" %
                                  (item.getURL(), item.getFailedReason()))

        if errorlines:
            if fetcher.getCaching() is NEVER:
                errorlines.insert(
                    0,
                    _("Failed acquiring information for '%s':") % self)
                raise Error, "\n".join(errorlines)
            return False

        if digest:
            self._digest = digest

        return True