["-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
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 ?
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"
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]"
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()
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)
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):
"""
"""
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")
line += w
if len(line) > 0:
rValue += line.replace(NEWLINE_ESCAPE, "\n")
+ rValue = rValue.replace(SPACE_ESCAPE, " ")
return rValue
def checkconfig(myconfig):
if not listnode.nodeName in ["ul", "ol"]:
raise GlsaFormatException("Invalid function call: listnode is not <ul> or <ol>")
for li in listnode.childNodes:
+ if li.nodeType != xml.dom.Node.ELEMENT_NODE:
+ continue
rValue.append(getText(li, format="strip"))
return rValue
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:
if format == "strip":
rValue = rValue.strip(" \n\t")
rValue = re.sub("[\s]{2,}", " ", rValue)
- return rValue
+ return str(rValue)
def getMultiTagsText(rootnode, tagname, format):
"""
@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):
"""
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
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
"""
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)
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()
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):