Convert bin/vulnxml2json.py to Python 3
authorRichard Levitte <levitte@openssl.org>
Tue, 14 Dec 2021 17:43:17 +0000 (18:43 +0100)
committerRichard Levitte <levitte@openssl.org>
Wed, 15 Dec 2021 10:13:50 +0000 (11:13 +0100)
It's starting to become impossible to install python 2 modules on
Debianesque machines, so we should move on to the new default.

Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/web/pull/282)

bin/vulnxml2json.py
bin/vulnxml2jsonproject.py

index 3b1dcbb0391d715a84f9292aae091624d5e281b5..f7657841a391e4d28c087c7eeef65452e64a51cb 100755 (executable)
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/python3
 #
 # Convert our XML file to a JSON file as accepted by Mitre for CNA purposes
 # as per https://github.com/CVEProject/automation-working-group/blob/master/cve_json_schema/DRAFT-JSON-file-format-v4.md
@@ -7,7 +7,7 @@
 #
 
 from xml.dom import minidom
-import HTMLParser
+import html
 import simplejson as json
 import codecs
 import re
@@ -34,15 +34,15 @@ parser.add_option("-o", "--outputdir", help="output directory for json file (def
 (options, args) = parser.parse_args()
 
 if not options.input:
-   print "needs input file"
+   print("needs input file")
    parser.print_help()
    exit();
 
 if options.schema:
    try:
-      response = urllib.urlopen(options.schema)
+      response = urllib.request.urlopen(options.schema)
    except:
-      print "Problem opening schema: try downloading it manually then specify it using --schema option: %s" % options.schema
+      print(f'Problem opening schema: try downloading it manually then specify it using --schema option: {options.schema}')
       exit()
    schema_doc = json.loads(response.read())
 
@@ -79,7 +79,7 @@ for issue in dom.getElementsByTagName('issue'):
             if desc:
                 desc += " "
             desc += re.sub('<[^<]+?>', '', d.toxml().strip())
-    desc = HTMLParser.HTMLParser().unescape(desc)
+    desc = html.unescape(desc)
     problemtype = "(undefined)"
     if issue.getElementsByTagName('problemtype'):
         problemtype = issue.getElementsByTagName('problemtype')[0].childNodes[0].nodeValue.strip()    
@@ -124,7 +124,7 @@ for issue in dom.getElementsByTagName('issue'):
         
     vv = list()
     for affects in issue.getElementsByTagName('fixed'): # OpenSSL and httpd since April 2018 does it this way
-       text = "Fixed in %s %s (Affected %s)" %(cfg.config['product_name'],affects.getAttribute('version'),cfg.merge_affects(issue,affects.getAttribute("base")))
+       text = f'Fixed in {cfg.config["product_name"]} {affects.getAttribute("version")} (Affected {cfg.merge_affects(issue,affects.getAttribute("base"))})'
        # Let's condense into a list form since the format of this field is 'free text' at the moment, not machine readable (as per mail with George Theall)
        vv.append({"version_value":text})
        # Mitre want the fixed/affected versions in the text too
@@ -132,7 +132,7 @@ for issue in dom.getElementsByTagName('issue'):
 
 #    if issue.getAttribute('fixed'): # httpd used to do it this way
 #        base = ".".join(issue.getAttribute("fixed").split('.')[:-1])+"."
-#        text = "Fixed in %s %s (Affected %s)" %(cfg.config['product_name'],issue.getAttribute('fixed'),cfg.merge_affects(issue,base))
+#        text = f'Fixed in {cfg.config["product_name"]} {cfg.merge_affects(issue,base)}'
 #        vv.append({"version_value":text})
 #        # Mitre want the fixed/affected versions in the text too
 #        desc += " "+text+"."            
@@ -151,17 +151,17 @@ for issue in cvej:
 
     f = codecs.open(options.outputdir+"/"+fn, 'w', 'utf-8')
     f.write(json.dumps(issue, sort_keys=True, indent=4, separators=(',',': ')))
-    print "wrote %s" %(options.outputdir+"/"+fn)
+    print(f'wrote {options.outputdir+"/"+fn}')
     f.close()
 
     try:
        validate(issue, schema_doc)
-       print "%s passed validation" % (fn)
+       print(f'{fn} passed validation')
     except jsonschema.exceptions.ValidationError as incorrect:
        v = Draft4Validator(schema_doc)
        errors = sorted(v.iter_errors(issue), key=lambda e: e.path)
        for error in errors:
-          print "%s did not pass validation: %s" % (fn,str(error.message))
+          print(f'{fn} did not pass validation: {str(error.message)}')
     except NameError:
-       print "%s skipping validation, no schema defined" %(fn)
+       print(f'{fn} skipping validation, no schema defined')
        
index bd7ba6523048a6a3a36a6f652c96f77f97e6c2b9..3cb4e314e4eaf23fe2d84c2c1d2544fac728f4ca 100644 (file)
@@ -23,7 +23,7 @@ def merge_affects(issue,base):
        if (not base or base in version):
            vlist.append(version)
     for ver in sorted(vlist):
-       # print "version %s (last was %s, next was %s)" %(ver,prev,anext)
+       # print(f'version {ver} (last was {prev}, next was {anext})')
        if (ver != anext):
           alist.append([ver])
        elif len(alist[-1]) > 1:
@@ -31,7 +31,7 @@ def merge_affects(issue,base):
        else:
           alist[-1].append(ver)
        prev = ver
-       if (unicode.isdigit(ver[-1])):   # First version after 1.0.1 is 1.0.1a
+       if (str.isdigit(ver[-1])):   # First version after 1.0.1 is 1.0.1a
            anext = ver + "a"
        elif (ver[-1] == "y"):
            anext = ver[:-1] + "za"    # We ran out of letters once so y->za->zb....