From 5764c32db099485eb69f6d683288235adb4937ba Mon Sep 17 00:00:00 2001 From: genone Date: Thu, 7 Oct 2004 00:06:47 +0000 Subject: [PATCH] Minor enhancements for glsa-check + major enhancements for glsa.py svn path=/; revision=146 --- trunk/ChangeLog | 8 +++ trunk/src/glsa-check/glsa-check | 23 +++++-- trunk/src/glsa-check/glsa.py | 117 ++++++++++++++++++++------------ 3 files changed, 98 insertions(+), 50 deletions(-) diff --git a/trunk/ChangeLog b/trunk/ChangeLog index fe46f86..517720b 100644 --- a/trunk/ChangeLog +++ b/trunk/ChangeLog @@ -1,3 +1,11 @@ +2004-10-06 Marius Mauch + * glsa.py: Convert Unicode strings to ascii before passing them to portage + * glsa.py: Some formatting fixes for dump() + * glsa.py: changed the matching routines so the reports are hopefully + more accurate + * glsa-check: added color support + * glsa-check: added a --verbose option to show the warnings about invalid GLSAs + 2004-09-27 Karl Trygve Kalleberg * Released gentoolkit-0.2.0_pre9 * Released gentoolkit-dev-0.2.0_pre4 diff --git a/trunk/src/glsa-check/glsa-check b/trunk/src/glsa-check/glsa-check index f7a0954..4d682f0 100644 --- a/trunk/src/glsa-check/glsa-check +++ b/trunk/src/glsa-check/glsa-check @@ -20,9 +20,10 @@ optionmap = [ ["-p", "--pretend", "show the necessary commands to apply this GLSA"], ["-f", "--fix", "try to auto-apply this GLSA (experimental)"], ["-i", "--inject", "inject the given GLSA into the checkfile"], -["-n", "--nocolor", "disable colors"], +["-n", "--nocolor", "disable colors (option)"], ["-h", "--help", "show this help message"], -["-v", "--version", "some information about this tool"] +["-V", "--version", "some information about this tool"], +["-v", "--verbose", "print more messages (option)"], ] # print a warning as this is beta code @@ -45,13 +46,19 @@ try: if option in args: nocolor() args.remove(option) + + verbose = False + for option in ["--verbose", "-v"]: + if option in args: + verbose = True + args.remove(option) # sanity checking if len(args) <= 0: print "no option given: what should I do ?" mode="help" elif len(args) > 1: - print "please use only one option per call" + print "please use only one command per call" mode = "help" else: # in what mode are we ? @@ -59,6 +66,7 @@ try: for m in optionmap: if args in [o for o in m[:-1]]: mode = m[1][2:] + except GetoptError, e: print "unknown option given:", e mode = "help" @@ -139,7 +147,8 @@ if mode == "list": try: myglsa = Glsa(myid, glsaconfig) except GlsaTypeException, e: - #print "invalid GLSA: %s (error message was: %s)" % (myid, e) + if verbose: + print "invalid GLSA: %s (error message was: %s)" % (myid, e) continue if myglsa.isApplied(): status = "[A]" @@ -164,7 +173,8 @@ if mode in ["dump", "fix", "inject", "pretend"]: try: myglsa = Glsa(myid, glsaconfig) except GlsaTypeException, e: - #print "invalid GLSA: %s (error message was: %s)" % (myid, e) + if verbose: + print "invalid GLSA: %s (error message was: %s)" % (myid, e) continue if mode == "dump": myglsa.dump() @@ -210,7 +220,8 @@ if mode == "test": try: myglsa = Glsa(myid, glsaconfig) except GlsaTypeException, e: - #print "invalid GLSA: %s (error message was: %s)" % (myid, e) + if verbose: + print "invalid GLSA: %s (error message was: %s)" % (myid, e) continue if myglsa.isVulnerable(): outputlist.append(myglsa.nr) diff --git a/trunk/src/glsa-check/glsa.py b/trunk/src/glsa-check/glsa.py index 842725a..dc7fd8e 100644 --- a/trunk/src/glsa-check/glsa.py +++ b/trunk/src/glsa-check/glsa.py @@ -24,6 +24,7 @@ import portage opMapping = {"le": "<=", "lt": "<", "eq": "=", "gt": ">", "ge": ">=", "rge": ">=~", "rle": "<=~", "rgt": " >~", "rlt": " <~"} NEWLINE_ESCAPE = "!;\\n" # some random string to mark newlines that should be preserved +SPACE_ESCAPE = "!;_" # some random string to mark spaces that should be preserved def center(text, width): """ @@ -68,12 +69,17 @@ def wrap(text, width, caption=""): """ rValue = "" line = caption + text = text.replace(2*NEWLINE_ESCAPE, NEWLINE_ESCAPE+" "+NEWLINE_ESCAPE) words = text.split() indentLevel = len(caption)+1 + for w in words: - if len(line)+len(w)+1 > width: + if line[-1] == "\n": + rValue += line + line = " "*indentLevel + if len(line)+len(w.replace(NEWLINE_ESCAPE, ""))+1 > width: rValue += line+"\n" - line = " "*indentLevel+w + line = " "*indentLevel+w.replace(NEWLINE_ESCAPE, "\n") elif w.find(NEWLINE_ESCAPE) >= 0: if len(line.strip()) > 0: rValue += line+" "+w.replace(NEWLINE_ESCAPE, "\n") @@ -87,6 +93,7 @@ def wrap(text, width, caption=""): line += w if len(line) > 0: rValue += line.replace(NEWLINE_ESCAPE, "\n") + rValue = rValue.replace(SPACE_ESCAPE, " ") return rValue def checkconfig(myconfig): @@ -154,6 +161,8 @@ def getListElements(listnode): if not listnode.nodeName in ["ul", "ol"]: raise GlsaFormatException("Invalid function call: listnode is not
    or
      ") for li in listnode.childNodes: + if li.nodeType != xml.dom.Node.ELEMENT_NODE: + continue rValue.append(getText(li, format="strip")) return rValue @@ -193,21 +202,23 @@ def getText(node, format): if subnode.nodeName == "p": for p_subnode in subnode.childNodes: if p_subnode.nodeName == "#text": - rValue += p_subnode.data + rValue += p_subnode.data.strip() elif p_subnode.nodeName in ["uri", "mail"]: rValue += p_subnode.childNodes[0].data rValue += " ( "+p_subnode.getAttribute("link")+" )" rValue += NEWLINE_ESCAPE elif subnode.nodeName == "ul": for li in getListElements(subnode): - rValue += "- "+li+NEWLINE_ESCAPE+" " + rValue += "-"+SPACE_ESCAPE+li+NEWLINE_ESCAPE+" " elif subnode.nodeName == "ol": i = 0 for li in getListElements(subnode): i = i+1 - rValue += str(i)+". "+li+NEWLINE_ESCAPE+" " + rValue += str(i)+"."+SPACE_ESCAPE+li+NEWLINE_ESCAPE+" " elif subnode.nodeName == "code": rValue += getText(subnode, format="keep").replace("\n", NEWLINE_ESCAPE) + if rValue[-1*len(NEWLINE_ESCAPE):] != NEWLINE_ESCAPE: + rValue += NEWLINE_ESCAPE elif subnode.nodeName == "#text": rValue += subnode.data else: @@ -215,7 +226,7 @@ def getText(node, format): if format == "strip": rValue = rValue.strip(" \n\t") rValue = re.sub("[\s]{2,}", " ", rValue) - return rValue + return str(rValue) def getMultiTagsText(rootnode, tagname, format): """ @@ -249,9 +260,10 @@ def makeAtom(pkgname, versionNode): @rtype: String @return: the portage atom """ - return opMapping[versionNode.getAttribute("range")] \ - +pkgname \ - +"-"+getText(versionNode, format="strip") + rValue = opMapping[versionNode.getAttribute("range")] \ + + pkgname \ + + "-" + getText(versionNode, format="strip") + return str(rValue) def makeVersion(versionNode): """ @@ -267,6 +279,24 @@ def makeVersion(versionNode): return opMapping[versionNode.getAttribute("range")] \ +getText(versionNode, format="strip") +def match(atom, portdbname): + """ + wrapper that calls revisionMatch() or portage.dbapi.match() depending on + the given atom. + + @type atom: string + @param atom: a <~ or >~ atom or a normal portage atom that contains the atom to match against + @type portdb: portage.dbapi + @param portdb: one of the portage databases to use as information source + + @rtype: list of strings + @return: a list with the matching versions + """ + if atom[2] == "~": + return revisionMatch(atom, portage.db["/"][portdbname].dbapi) + else: + return portage.db["/"][portdbname].dbapi.match(atom) + def revisionMatch(revisionAtom, portdb): """ handler for the special >~, >=~, <=~ and <~ atoms that are supposed to behave @@ -310,35 +340,34 @@ def getMinUpgrade(vulnerableList, unaffectedList): the installed version. """ rValue = None + v_installed = [] + u_installed = [] for v in vulnerableList: - if v[2] == "~": - installed = revisionMatch(v, portage.db["/"]["vartree"].dbapi) + v_installed += match(v, "vartree") + + for u in unaffectedList: + u_installed += match(u, "vartree") + + install_unaffected = True + for i in v_installed: + if i not in u_installed: + install_unaffected = False + + if install_unaffected: + return [] + + for u in unaffectedList: + if u[2] == "~": + mylist = revisionMatch(u, portage.db["/"]["porttree"].dbapi) else: - installed = portage.db["/"]["vartree"].dbapi.match(v) - if not installed: - continue - for u in unaffectedList: - install_unaffected = True - for i in installed: - if u[2] == "~": - myinstalledlist = revisionMatch(u, portage.db["/"]["vartree"].dbapi) - else: - myinstalledlist = portage.db["/"]["vartree"].dbapi.match(u) - if not i in myinstalledlist: - install_unaffected = False - if install_unaffected: - break - if u[2] == "~": - mylist = revisionMatch(u, portage.db["/"]["porttree"].dbapi) - else: - mylist = portage.db["/"]["porttree"].dbapi.match(u) - for c in mylist: - c_pv = portage.catpkgsplit(c) - i_pv = portage.catpkgsplit(portage.best(installed)) - if portage.pkgcmp(c_pv[1:], i_pv[1:]) > 0 and (rValue == None or portage.pkgcmp(c_pv[1:], rValue) < 0): - rValue = c_pv[0]+"/"+c_pv[1]+"-"+c_pv[2] - if c_pv[3] != "r0": # we don't like -r0 for display - rValue += "-"+c_pv[3] + mylist = portage.db["/"]["porttree"].dbapi.xmatch("match-all", u) + for c in mylist: + c_pv = portage.catpkgsplit(c) + i_pv = portage.catpkgsplit(portage.best(v_installed)) + if portage.pkgcmp(c_pv[1:], i_pv[1:]) > 0 and (rValue == None or portage.pkgcmp(c_pv[1:], rValue) < 0): + rValue = c_pv[0]+"/"+c_pv[1]+"-"+c_pv[2] + if c_pv[3] != "r0": # we don't like -r0 for display + rValue += "-"+c_pv[3] return rValue # simple Exception classes to catch specific errors @@ -479,7 +508,7 @@ class Glsa: """ myfile = codecs.open(outfile, "w", encoding) width = int(self.config["PRINTWIDTH"]) - myfile.write(center("GLSA %s: %s" % (self.nr, self.title), width)+"\n") + myfile.write(center("GLSA %s: \n%s" % (self.nr, self.title), width)+"\n") myfile.write((width*"=")+"\n") myfile.write(wrap(self.synopsis, width, caption="Synopsis: ")+"\n") myfile.write("Announced on: %s\n" % self.announced) @@ -514,9 +543,10 @@ class Glsa: myfile.write("\n"+wrap(self.impact_text, width, caption="Impact: ")) myfile.write("\n"+wrap(self.workaround, width, caption="Workaround: ")) myfile.write("\n"+wrap(self.resolution, width, caption="Resolution: ")) - myfile.write("\nReferences: ") + myreferences = "" for r in self.references: - myfile.write(r+"\n"+19*" ") + myreferences += (r.replace(" ", SPACE_ESCAPE)+NEWLINE_ESCAPE+" ") + myfile.write("\n"+wrap(myreferences, width, caption="References: ")) myfile.write("\n") myfile.close() @@ -535,11 +565,10 @@ class Glsa: pkg = self.packages[k] for path in pkg: if path["arch"] == "*" or self.config["ARCH"] in path["arch"].split(): - vList += path["vul_atoms"] - for v in vList: - rValue = rValue \ - or (len(portage.db["/"]["vartree"].dbapi.match(v)) > 0 \ - and getMinUpgrade(vList, path["unaff_atoms"])) + for v in path["vul_atoms"]: + rValue = rValue \ + or (len(match(v, "vartree")) > 0 \ + and getMinUpgrade(path["vul_atoms"], path["unaff_atoms"])) return rValue def isApplied(self): -- 2.26.2