def enableChannel(self, apturl): # ensure that no funny path tricks can be played # by e.g. passing "apt:foo?channel=../../" channel = os.path.basename(apturl.channel) channelpath = "%s/%s.list" % (channelsdir,channel) channelkey = "%s/%s.key" % (channelsdir,channel) channelhtml = "%s/%s.eula" % (channelsdir,channel) # check if not os.path.exists(channelpath): self.ui.error(_("Unknown channel '%s'") % channel, _("The channel '%s' is not known") % channel) return RESULT_ERROR channel_info_html = "" if os.path.exists(channelhtml): channel_info_html = open(channelhtml).read() if not self.ui.askEnableChannel(apturl.channel, channel_info_html): return RESULT_CANCELT if not self.ui.doEnableChannel(channelpath, channelkey): self.ui.error(_("Enabling channel '%s' failed") % apturl.channel) return RESULT_ERROR self.ui.doUpdate() self.openCache() return RESULT_OK
def set_value(apt_url, s): " set a key,value pair from string s to AptUrl object " (key, value) = s.split("=") try: if ' ' in value: raise InvalidUrlException(apt_url, _("Whitespace in key=value")) if type(getattr(apt_url, key)) == type([]): getattr(apt_url, key).append(value) else: setattr(apt_url, key, value) except Exception, e: raise InvalidUrlException(apt_url, _("Exception '%s'") % e)
def parse(full_url, mapping=apturl_substitution_mapping): " parse an apt url and return a list of AptUrl objects " # apt:pkg1?k11=v11?k12=v12,pkg2?k21=v21?k22=v22,... res = [] if len(full_url) > MAX_URL_LEN: url = "%s ..." % full_url[0:MAX_URL_LEN/10] raise InvalidUrlException(url, _("Url string '%s' too long") % url) # check against whitelist match_against_whitelist(full_url) for url in full_url.split(";"): if not ":" in url: raise InvalidUrlException(url, _("No ':' in the uri")) # now parse it (schema, packages) = url.split(":", 1) packages = packages.split(",") for package in packages: apt_url = AptUrl() apt_url.schema = schema # check for schemas of the form: apt+http:// if schema.startswith("apt+"): apt_url.repo_url = schema[len("apt+"):] + ":" + package.split("?",1)[0] else: if "?" in package: apt_url.package = package.split("?")[0].lstrip("/") else: apt_url.package = package.lstrip("/") # now parse the ?... bits if "?" in package: key_value_pairs = package.split("?")[1:] for s in key_value_pairs: if "&" in s: and_key_value_pairs = s.split("&") for s in and_key_value_pairs: set_value(apt_url, s) else: set_value(apt_url, s) # do substitution (if needed) do_apt_url_substitution(apt_url, mapping) # check if the package name is valid if not is_format_package_name(apt_url.package): raise InvalidUrlException(url, "Invalid package name '%s'" % apt_url.package) res.append(apt_url) return res
def enableSection(self, apturl): added = False # parse sources.list sourceslist = SourcesList() distro = aptsources.distro.get_distro() distro.get_sources(sourceslist) # check if we actually need to enable anything requested_components = [] for component in apturl.section: if not component in distro.enabled_comps: requested_components.append(component) # if not, we are fine if not requested_components: return RESULT_OK # otherwise ask the user if the really wants to anble them if not self.ui.askEnableSections(apturl.section): return RESULT_CANCELT if not self.ui.doEnableSection(apturl.section): self.ui.error(_("Enabling '%s' failed") % ", ".join(apturl.section)) return RESULT_ERROR self.ui.doUpdate() self.openCache() return RESULT_OK
def openCache(self): try: self.cache = apt.Cache() except SystemError, strerr: if not '/etc/apt/sources.list' in str(strerr): raise self.ui.error(_("Invalid /etc/apt/sources.list file"), strerr) return False
def askEnableSections(self, sections): " generic implementation, can be overridden " return self.yesNoQuestion( _("Enable additional components"), _n( "Do you want to enable the following " "component: '%s'?", "Do you want to enable the following " "components: '%s'?", len(sections), ) % ", ".join(sections), )
def parseArgs(self): parser = OptionParser() parser.add_option("-p", "--http-proxy", dest="http_proxy", default=None, help="use http proxy") (options, args) = parser.parse_args() # eval and add proxy if options.http_proxy is not None: proxy = options.http_proxy if not ":" in proxy: proxy += ":3128" os.environ["http_proxy"] = "http://%s" % proxy # parse try: apturl_list = Parser.parse(args[0]) except IndexError, e: self.ui.error(_("Need a url to continue, exiting")) return []
def askEnableChannel(self, channel, channel_info_html): " generic implementation, can be overridden " return self.yesNoQuestion( _("Enable additional software channel"), _("Do you want to enable the following " "software channel: '%s'?") % channel, )
def main(self): # global return code ret = RESULT_OK ui = self.ui # parse arguments apturl_list = self.parseArgs() if not apturl_list: return RESULT_BADARGS # open cache if not self.openCache(): return RESULT_ERROR # now go over the url list for apturl in apturl_list: # FIXME: move this code block into a func like # evalAptUrl() if not apturl.schema in ("apt", "apt+http"): self.ui.error(_("Can not deal with protocol '%s' ") % apturl.schema) continue if apturl.section: if self.enableSection(apturl) != RESULT_OK: continue elif apturl.channel: if self.enableChannel(apturl) != RESULT_OK: continue elif apturl.refresh is not None: ui.doUpdate() if not self.openCache(): return RESULT_ERROR # now check the package if not self.cache.has_key(apturl.package): try: package_in_cache = bool(self.cache._cache[apturl.package]) except KeyError: package_in_cache = False if package_in_cache: ui.error(_("Package '%s' is virtual.") % apturl.package) continue else: ui.error(_("Could not find package '%s'.") % apturl.package) continue if self.cache[apturl.package].isInstalled and apturl.minver is None: ui.message(_("Package '%s' is already installed") % apturl.package) continue # ask the user pkg = self.cache[apturl.package] (sum, desc, homepage) = Helpers.parse_pkg(pkg) if not ui.askInstallPackage(apturl.package, sum, desc, homepage): ret = RESULT_CANCELT continue # try to install it try: self.cache[apturl.package].markInstall() except SystemError, e: ui.error(_("Can not install '%s' (%s) ") % (apturl.package, e)) continue if apturl.minver is not None: verStr = self.cache[apturl.package].candidateVersion if apt_pkg.VersionCompare(verStr, apturl.minver) < 1: ui.error(_("Package '%s' requests minimal version '%s', but " "only '%s' is available") % (apturl.package, apturl.minver, verStr)) continue # install it ui.doInstall(apturl) if not self.verifyInstall(apturl): ret = RESULT_ERROR
# eval and add proxy if options.http_proxy is not None: proxy = options.http_proxy if not ":" in proxy: proxy += ":3128" os.environ["http_proxy"] = "http://%s" % proxy # parse try: apturl_list = Parser.parse(args[0]) except IndexError, e: self.ui.error(_("Need a url to continue, exiting")) return [] except Parser.InvalidUrlException, e: self.ui.error(_("Invalid url: '%s' given, exiting") % e.url.decode('utf-8'), unicode(e)) return [] return (apturl_list) def verifyInstall(self, apturl): " verify that the install package actually is installed " # check if the package got actually installed self.openCache() pkg = self.cache[apturl.package] if (not pkg.isInstalled or pkg._pkg.CurrentState != apt_pkg.CurStateInstalled or self.cache._depcache.BrokenCount > 0): return False return True
def match_against_whitelist(raw_url): " test if the url matches the internal whitelist " for char in raw_url: if not char in whitelist: raise InvalidUrlException(raw_url, _("Non whitelist char in the uri")) return True
# eval and add proxy if options.http_proxy is not None: proxy = options.http_proxy if not ":" in proxy: proxy += ":3128" os.environ["http_proxy"] = "http://%s" % proxy # parse try: apturl_list = Parser.parse(args[0]) except IndexError, e: self.ui.error(_("Need a url to continue, exiting")) return [] except Parser.InvalidUrlException, e: self.ui.error(_("Invalid url: '%s' given, exiting") % e.url, "%s" % str(e)) return [] return (apturl_list) def verifyInstall(self, apturl): " verify that the install package actually is installed " # check if the package got actually installed self.openCache() pkg = self.cache[apturl.package] if (not pkg.isInstalled or pkg._pkg.CurrentState != apt_pkg.CurStateInstalled or self.cache._depcache.BrokenCount > 0): return False return True