# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from sys import argv from os import popen from os import popen4 from os import spawnl from os.path import isdir from os.path import walk from os.path import split from os.path import splitext from os.path import exists from tempfile import mkdtemp from os.path import join from os import listdir from os import rmdir from os import makedirs from shutil import rmtree import md5 import sha class UserAbortError(Exception): def __str__(self): return "Aborted by user. Bye." def matchExtension(file, dir, extension): matches = [] extension = '.' + extension.lower() for element in listdir(dir): root, ext = splitext(element) if extension == ext.lower() and root == file: matches.append(element) return matches def printMatches(file, dir, extension): matches = matchExtension(file, dir, extension) for match in matches: matchFile = open(join(dir,match), 'r') text = matchFile.read(); matchFile.close() print text def untgz(file, dir): popen("tar -xzf " + file + " -C " + dir) def unzip(file, dir): popen("unzip -d " + dir + " " + file) def checkSums(filename, dir): file = open(join(dir, filename), 'r') contents = file.read() file.close() md5sum = md5.new() md5sum.update(contents) print "MD5:" print md5sum.hexdigest() printMatches(filename, dir, "MD5") shaSum = sha.new() shaSum.update(contents) print "SHA1:" print shaSum.hexdigest() printMatches(filename, dir, "SHA") printMatches(filename, dir, "SHA1") def checkSignature(filename, dir, gpgCommand): file = join(dir, filename) signatureFile = file + '.asc' if not(exists(signatureFile)): signatureFile = file + '.sig' if not(exists(signatureFile)): print "SIGNATURE IS MISSING" command = gpgCommand + ' --verify ' + signatureFile + ' ' + file input, output = popen4(command) print output.read() def rat(file, dir, uncompress, ratCommand, baseReportDirectory): if baseReportDirectory == None: reportdir = mkdtemp() else: reportdir = join(baseReportDirectory, file.replace('.', '_')) if exists(reportdir): rmtree(reportdir) makedirs(reportdir) uncompress(join(dir, file), reportdir) command = ratCommand + " " + reportdir input, output = popen4(command) out = output.read() if not baseReportDirectory == None: f = open(join(baseReportDirectory, file + '.rat'), 'w') f.write(out) f.close() print out def checkArchive(file, dir, uncompress, ratCommand, gpgCommand, baseReportDirectory): print "." print "." print "." print "###################################################" print "Checking ", file checkSums(file, dir) checkSignature(file, dir, gpgCommand) rat(file, dir, uncompress, ratCommand, baseReportDirectory) print "###################################################" print "." print "." print "." def checkFile(file, dir, ratCommand, gpgCommand, baseReportDirectory): '''Checks the given file''' if file.endswith('.jar'): print "Checking jar ", file checkArchive(file, dir, lambda a,b:unzip(a,b), ratCommand, gpgCommand, baseReportDirectory) elif file.endswith('.zip'): print "Checking zip ", file checkArchive(file, dir, lambda a,b:unzip(a,b), ratCommand, gpgCommand, baseReportDirectory) elif file.endswith('.tar.gz') or file.endswith('.tgz'): print "Checking tgz ", file checkArchive(file, dir, lambda a,b:untgz(a,b), ratCommand, gpgCommand, baseReportDirectory) def ignoreDirectory(dir): '''Is this directory to be ignored?''' if dir == "": return False else: head, tail = split(dir) if tail.startswith('.') and not(tail.startswith('..')): return True elif tail == "": return False else: return ignoreDirectory(head) def checkDirectory(ratCommand, gpgCommand, dir, files, baseReportDir, check=lambda a,b,c,d: lambda x: checkFile(x,a,b,c,d)): '''Checks a directory''' if not(ignoreDirectory(dir)): print 'Checking directory ', dir map(check(dir, ratCommand, gpgCommand, baseReportDir), files) def walkDirectories(base, ratCommand, gpgCommand, baseReportDir = None, f=lambda a,b,c,d,e: checkDirectory(a,b,c,d,e)): '''Traverses directories under base and executes checks''' print 'Starting traversal at ', base walk(base, lambda dummy, dir, files: f(ratCommand, gpgCommand, dir, files, baseReportDir), None) def enterRatCommand(rat = None): '''If necessary, prompts user for an acceptable Rat command''' if rat == None: try: rat = raw_input("Please enter Rat command (including path): ") except EOFError: raise UserAbortError() if rat == "": print "Rat command is required" rat = enterRatCommand() ratResult = popen(rat).close() if not(ratResult == None): print "Cannot execute " + rat rat = enterRatCommand() return rat def enterBaseDirectory(base = None): '''If necessary prompts user for an acceptable base directory''' if base == None: try: base = raw_input("Please enter base directory for recursive traversal: ") except EOFError: raise UserAbortError() if not(isdir(base)): print "'" + base + "' is not a directory." base = enterBaseDirectory() return base def enterGPGCommand(gpgCommand = None): '''If necessary prompts user for the command used to test signatures''' if gpgCommand == None: try: gpgCommand = raw_input("GnuPG is required. Please enter GPG command: ") except EOFError: raise UserAbortError() result = popen(gpgCommand + " --version").close() if not(result == None): print "Cannot execute " + gpgCommand rat = enterGPGCommand() return gpgCommand def getRatCommand(): '''Gets an acceptable value for the Rat command''' if len(argv) == 1: ratCommand = enterRatCommand() else: ratCommand = enterRatCommand(argv[1]) return ratCommand def getBaseDirectory(): '''Gets an acceptable value for the base directory''' if len(argv) < 3: base = enterBaseDirectory() else: base = enterBaseDirectory(argv[2]) return base def getGPGCommand(): '''Gets an acceptable value for the command used to test signatures''' if len(argv) < 5: gpgCommand = enterGPGCommand('gpg') else: gpgCommand = enterGPGCommand(argv[4]) return gpgCommand def getBaseReportDirectory(): if len(argv) < 4: return None else: return argv[3] def checkArgs(f=lambda a,b,c,d: walkDirectories(a, b, c, d)): '''Prompts user for arguments missing from the command line. Check argument values.''' try: ratCommand = getRatCommand() base = getBaseDirectory() gpgCommand = getGPGCommand() baseReportDirectory = getBaseReportDirectory() f(base, ratCommand, gpgCommand, baseReportDirectory) except UserAbortError, e: print '\n' print e checkArgs()