def check(self, path: str) -> None: """ the real check """ super(UniventionPackageCheck, self).check(path) tester = uub.UPCFileTester() tester.addTest( re.compile(r'''(?:(?<=['" \t])|^)(?:/usr/sbin/)?univention-admin(?=['" \t]|$)'''), '0016-2', 'Use of deprecated "univention-admin"', cntmax=0) tester.addTest( re.compile(r'''(?:(?<=['" \t])|^)(?:/usr/sbin/)?univention-baseconfig(?=["' \t]|$)'''), '0016-3', 'Use of deprecated "univention-baseconfig"', cntmax=0) tester.addTest( re.compile(r'''\bfrom\b.+\bunivention_baseconfig\b.+\bimport\b|\bimport\b.+\bunivention_baseconfig\b'''), '0016-4', 'Use of deprecated "univention_baseconfig"', cntmax=0) tester.addTest( re.compile(r'''@%@BCWARNING=.+?@%@'''), '0016-5', 'Use of deprecated "@%@BCWARNING=@%@"', cntmax=0) ignore_suffixes = ('.1', '.2', '.3', '.4', '.5', '.6', '.7', '.8', '.txt') ignore_files = ('changelog', 'README') for fn in uub.FilteredDirWalkGenerator(path, ignore_suffixes=ignore_suffixes, ignore_files=ignore_files): tester.open(fn) msglist = tester.runTests() self.msg.extend(msglist) for fn in uub.FilteredDirWalkGenerator(os.path.join(path, 'debian'), suffixes=('.univention-baseconfig',)): self.addmsg('0016-6', 'Use of deprecated "debian/*.univention-baseconfig"', fn)
def check(self, path: str) -> None: """ the real check """ super(UniventionPackageCheck, self).check(path) self.check_py(python_files(path)) self.check_po(uub.FilteredDirWalkGenerator(path, suffixes=('.po',))) self.check_names(uub.FilteredDirWalkGenerator( path, ignore_suffixes=uub.FilteredDirWalkGenerator.BINARY_SUFFIXES | uub.FilteredDirWalkGenerator.DOCUMENTATION_SUFFIXES, ))
def find_python_files(self, base): pathes = set( list(uub.FilteredDirWalkGenerator(base, suffixes=['.py'])) + list( uub.FilteredDirWalkGenerator(base, ignore_suffixes=['.py'], reHashBang=self.PYTHON_HASH_BANG)) ) for path in pathes: if not self.ignore_path(path): yield path
def check(self, path): """ the real check """ super(UniventionPackageCheck, self).check(path) files = [] # scan directory only for dir in ['debian']: for fn in os.listdir(os.path.join(path, dir)): self.debug(os.path.join(path, dir, fn)) if not os.path.isdir(os.path.join(path, dir, fn)): files.append(os.path.join(path, dir, fn)) # scan directory recursively for dir in ['conffiles']: for fn in uub.FilteredDirWalkGenerator(os.path.join(path, dir)): files.append(fn) for fn in files: try: content = open(fn, 'r').read() except (OSError, IOError): self.addmsg('0002-1', 'failed to open and read file', fn) continue for txt in ['dc=univention,dc=local', 'dc=univention,dc=qa', 'dc=univention,dc=test']: for line in self._searchString(content, txt): self.addmsg('0002-2', 'contains invalid basedn', fn, line) for txt in ['univention.local', 'univention.qa', 'univention.test']: for line in self._searchString(content, txt): self.addmsg('0002-3', 'contains invalid domainname', fn, line)
def check(self, path: str) -> None: """ the real check """ super(UniventionPackageCheck, self).check(path) for fn in uub.FilteredDirWalkGenerator( path, ignore_suffixes=uub.FilteredDirWalkGenerator.BINARY_SUFFIXES): try: with open(fn, 'r') as fd: for row, line in enumerate(fd, start=1): origline = line if self.RE_WHITELINE.match(line): continue for match in RE_UNIVENTION.finditer(line): found = match.group(0) if self.RE_WHITEWORD.match(found): continue self.debug('%s:%d: found="%s" origline="%s"' % (fn, row, found, origline)) self.addmsg( '0015-2', 'univention is incorrectly spelled: %s' % found, fn, row) except UnicodeDecodeError: # Silently skip binary files pass
def check(self, path): """ the real check """ super(UniventionPackageCheck, self).check(path) fz = tre.Fuzzyness(maxerr=2) pt = tre.compile("\<univention\>", tre.EXTENDED | tre.ICASE) for fn in uub.FilteredDirWalkGenerator(path): fd = open(fn, 'r') try: for lnr, line in enumerate(fd, start=1): origline = line if UniventionPackageCheck.RE_WHITELINE.match(line): continue pos = 0 while True: m = pt.search(line[pos:], fz) if m: if not UniventionPackageCheck.RE_WHITEWORD.match( m[0]): self.debug('%s:%d: found="%s" origline="%s"' % (fn, lnr, m[0], origline)) self.addmsg( '0015-2', 'univention is incorrectly spelled: %s' % m[0], filename=fn, line=lnr) pos += m.groups()[0][1] else: break finally: fd.close()
def check(self, path: str) -> None: """ the real check """ super(UniventionPackageCheck, self).check(path) tester = uub.UPCFileTester() tester.addTest(re.compile(r'dc=univention,dc=(?:local|qa|test)'), '0002-2', 'contains invalid basedn', cntmax=0) tester.addTest(re.compile(r'univention\.(?:local|qa|test)'), '0002-3', 'contains invalid domainname', cntmax=0) for fn in chain( uub.FilteredDirWalkGenerator(join(path, 'conffiles')), uub.FilteredDirWalkGenerator(join(path, 'debian')), ): try: tester.open(fn) except EnvironmentError: self.addmsg('0002-1', 'failed to open and read file', fn) else: self.msg += tester.runTests()
def check(self, path): """ the real check """ super(UniventionPackageCheck, self).check(path) py_files = [] for fn in uub.FilteredDirWalkGenerator(path): if fn.endswith('.py'): # add all files to list that end with ".py" py_files.append(fn) continue try: content = open(fn, 'r').read(100) # add all files that contain a hashbang in first line except (IOError, OSError): self.debug('Failed to read 100 bytes from %r' % (fn,)) else: if content.startswith('#!'): py_files.append(fn) tester = uub.UPCFileTester() tester.addTest(re.compile('.has_key\s*\('), '0009-5', 'dict.has_key is deprecated in python3 - please use "if key in dict:"', cntmax=0) tester.addTest(re.compile(r'''\braise\s*(?:'[^']+'|"[^"]+")'''), '0009-6', 'raise "text" is deprecated in python3', cntmax=0) tester.addTest(re.compile(r"""\b(?:if|while)\b.*(?:(?:!=|<>|==)\s*None\b|\bNone\s*(?:!=|<>|==)).*:"""), '0009-7', 'fragile comparison with None', cntmax=0) tester.addTest(re.compile( r'''(?:baseConfig|configRegistry|ucr)(?:\[.+\]|\.get\(.+\)).*\bin\s* [[(] (?:\s*(['"])(?:yes|no|1|0|true|false|on|off|enabled?|disabled?)\1\s*,?\s*){3,} [])]''', re.VERBOSE | re.IGNORECASE), '0009-8', 'use ucr.is_true() or .is_false()', cntmax=0) for fn in py_files: try: content = open(fn, 'r').read(100) except (IOError, OSError): self.addmsg('0009-1', 'failed to open and read file', filename=fn) continue self.debug('testing %s' % fn) if not content: continue tester.open(fn) msglist = tester.runTests() self.msg.extend(msglist) firstline = content.splitlines()[0] match = UniventionPackageCheck.RE_HASHBANG.match(firstline) if match: version, space, option, tail = match.groups() if not version: self.addmsg('0009-2', 'file does not specify python version in hashbang', filename=fn) elif version != '2.7': self.addmsg('0009-3', 'file specifies wrong python version in hashbang', filename=fn) if space and not option: self.addmsg('0009-4', 'file contains whitespace after python command', filename=fn) if tail: self.addmsg('0009-9', 'hashbang contains more than one option', filename=fn)
def check(self, path): """ the real check """ super(UniventionPackageCheck, self).check(path) for fn in uub.FilteredDirWalkGenerator( path, ignore_suffixes=['~', '.py', '.bak', '.po'], reHashBang=re.compile('^#![ \t]*/bin/(?:d?a)?sh')): self.debug('Testing file %s' % fn) self.check_bashism(fn) self.check_unquoted_local(fn)
def check(self, path): """ the real check """ super(UniventionPackageCheck, self).check(path) # # search shell scripts and execute test # for fn in uub.FilteredDirWalkGenerator(path): if fn.endswith('.sh') or containsHashBang(fn): self.tester.open(fn) msglist = self.tester.runTests() self.msg.extend(msglist)
def check(self, path: str) -> None: """ the real check """ super(UniventionPackageCheck, self).check(path) for fn in uub.FilteredDirWalkGenerator(path, ignore_suffixes=['.po'], reHashBang=RE_HASHBANG_SHELL): self.debug('Testing file %s' % fn) try: self.check_bashism(fn) self.check_unquoted_local(fn) except (EnvironmentError, UnicodeDecodeError): self.addmsg('0013-1', 'failed to open file', fn)
def check_dirs(self, path: str) -> None: dirs = {} # type: Dict[str, Set[str]] debianpath = join(path, 'debian') for fp in uub.FilteredDirWalkGenerator(debianpath, suffixes=['install']): package, suffix = self.split_pkg(fp) pkg = dirs.setdefault(package, Dirs(package)) # ~/doc/2018-04-11-ApiDoc/pymerge for row, line in self.lines(fp): dst = '' for src, dst in self.process_install(line): self.debug('%s:%d Installs %s to %s' % (fp, row, src, dst)) pkg.add(dst) if self.RE_PYTHONPATHS.match(dst): self.addmsg( '0018-4', 'Use debian/*.pyinstall to install Python modules', fp, row) for fp in uub.FilteredDirWalkGenerator(debianpath, suffixes=['pyinstall']): package, suffix = self.split_pkg(fp) pkg = dirs.setdefault(package, Dirs(package)) for row, line in self.lines(fp): for src, dst in self.process_pyinstall(line): self.debug('%s:%d Installs %s to %s' % (fp, row, src, dst)) pkg.add(dst) for fp in uub.FilteredDirWalkGenerator(debianpath, suffixes=['dirs']): package, suffix = self.split_pkg(fp) pkg = dirs.setdefault(package, Dirs(package)) for row, line in self.lines(fp): line = line.strip('/') if line in pkg: self.addmsg('0018-2', 'Unneeded directory %r' % (line, ), fp, row)
def check(self, path): """ the real check """ super(UniventionPackageCheck, self).check(path) py_files = [] po_files = [] for fn in uub.FilteredDirWalkGenerator(path, suffixes=('.py', '.po')): if fn.endswith('.py'): py_files.append(fn) if fn.endswith('.po'): po_files.append(fn) self.check_py(py_files) self.check_po(po_files)
def check(self, path: str) -> None: """ the real check """ super(UniventionPackageCheck, self).check(path) # # search shell scripts and execute test # for fn in uub.FilteredDirWalkGenerator(path, suffixes=['.sh'], reHashBang=RE_HASHBANG_SHELL): try: self.tester.open(fn) except EnvironmentError: continue else: msglist = self.tester.runTests() self.msg.extend(msglist)
def check_conffiles(self, python: str) -> List[str]: errors = [] # type: List[str] header_length = len(UCR_HEADER.splitlines()) + 1 for conffile in uub.FilteredDirWalkGenerator('conffiles'): with open(conffile, 'r') as fd: text = fd.read() for match in EXECUTE_TOKEN.findall(text): leading_lines = len(text[:text.index(match)].splitlines()) match = match.rstrip() + '\n' # prevent "blank line at end of file" and "blank line contains whitespace" false positives for error in self.flake8(python, ['-'], self.DEFAULT_IGNORE, UCR_HEADER + match): try: errno, filename, row, col, descr = error.split(' ', 4) row = str(int(row) - header_length + leading_lines) except ValueError as ex: # flake8 --show-source provides 2 extra lines self.debug('%s: %s' % (ex, error)) continue errors.append(' '.join((errno, conffile, row, col, descr))) return errors
def check(self, path): """ the real check """ super(UniventionPackageCheck, self).check(path) for fn in uub.FilteredDirWalkGenerator( path, ignore_suffixes=self.BINARY_SUFFIXES): with open(fn, 'r') as fd: for lnr, line in enumerate(fd, start=1): origline = line if UniventionPackageCheck.RE_WHITELINE.match(line): continue for match in RE_UNIVENTION.finditer(line): found = match.group(0) if UniventionPackageCheck.RE_WHITEWORD.match(found): continue self.debug('%s:%d: found="%s" origline="%s"' % (fn, lnr, found, origline)) self.addmsg('0015-2', 'univention is incorrectly spelled: %s' % found, filename=fn, line=lnr)
def check_conffiles(self, path: str) -> Dict[str, Any]: """Analyze UCR templates below :file:`conffiles/`.""" conffiles = {} # type: Dict[str, Dict[str, Any]] confdir = os.path.join(path, 'conffiles') for fn in uub.FilteredDirWalkGenerator(confdir, ignore_suffixes=uub.FilteredDirWalkGenerator.BINARY_SUFFIXES): checks = { 'headerfound': False, 'variables': [], # List[str] # Python code 'placeholder': [], # List[str] # @%@ 'ucrwarning': False, 'pythonic': False, 'preinst': False, 'postinst': False, 'handler': False, 'custom_user': False, 'custom_group': False, } # type: Dict[str, Any] conffiles[fn] = checks match = self.RE_PYTHON_FNAME.match(os.path.relpath(fn, confdir)) if match: checks['pythonic'] = True try: content = open(fn, 'r').read() except EnvironmentError: self.addmsg('0004-27', 'cannot open/read file', fn) continue except UnicodeDecodeError as ex: self.addmsg('0004-30', 'contains invalid characters', fn, ex.start) continue match = self.RE_FUNC_PREINST.search(content) if match: checks['preinst'] = True match = self.RE_FUNC_POSTINST.search(content) if match: checks['postinst'] = True match = self.RE_FUNC_HANDLER.search(content) if match: checks['handler'] = True match = self.RE_FUNC_CUSTOM_USER.search(content) if match: checks['custom_user'] = True match = self.RE_FUNC_CUSTOM_GROUP.search(content) if match: checks['custom_group'] = True warning_pos = 0 for match in self.RE_UCR_PLACEHOLDER_VAR1.finditer(content): var = match.group(1) if var.startswith('BCWARNING=') or var.startswith('UCRWARNING=') or var.startswith('UCRWARNING_ASCII='): checks['ucrwarning'] = True warning_pos = warning_pos or match.start() + 1 elif var not in checks['placeholder']: checks['placeholder'].append(var) if checks['placeholder']: self.debug('found UCR placeholder variables in %s\n- %s' % (fn, '\n- '.join(checks['placeholder']))) match = self.RE_IDENTIFIER.search(content, 0) if warning_pos and match: identifier = match.group() pos = match.start() self.debug('Identifier "%s" found at %d' % (identifier, pos)) if warning_pos < pos: self.addmsg('0004-34', 'UCR warning before file type magic "%s"' % (identifier,), fn) # # subcheck: check if UCR header is present # if 'Warning: This file is auto-generated and might be overwritten by' in content and \ 'Warnung: Diese Datei wurde automatisch generiert und kann durch' in content: checks['headerfound'] = True for regEx in self.RE_UCR_VARLIST: for match in regEx.finditer(content): var = match.group(1) if var not in checks['variables']: checks['variables'].append(var) if checks['variables']: self.debug('found UCR variables in %s\n- %s' % (fn, '\n- '.join(checks['variables']))) if checks['headerfound']: # # subcheck: check if path in UCR header is correct # match = self.RE_UCR_HEADER_FILE.search(content) if match: fname = fn[fn.find('/conffiles/') + 10:] if match.group(2) != fname: self.addmsg('0004-1', 'Path in UCR header seems to be incorrect.\n - template filename = /etc/univention/templates/files%s\n - path in header = %s' % (fname, match.group(1)), fn) self.debug('found conffiles: %s' % conffiles.keys()) return conffiles
def check(self, path: str) -> None: """ the real check """ super(UniventionPackageCheck, self).check(path) fnlist_joinscripts = {} # # search join scripts # for f in os.listdir(path): if not f[0:2].isdigit(): continue fn = os.path.join(path, f) if f.endswith('.inst'): fnlist_joinscripts[fn] = CALLED elif f.endswith('.uinst'): fnlist_joinscripts[fn] = CALLED | COPIED else: continue self.debug('found %s' % fn) # # check if join scripts use versioning # for js in fnlist_joinscripts: self.check_join_script(js) # # check if join scripts are present in debian/rules || debian/*.install # found = {} # type: Dict[str, int] debianpath = os.path.join(path, 'debian') # get all .install files fnlist = list( uub.FilteredDirWalkGenerator(debianpath, suffixes=['.install'])) # append debian/rules fn_rules = os.path.join(path, 'debian', 'rules') fnlist.append(fn_rules) # Look for dh-umc-modules-install try: content = open(fn_rules, 'r').read() except EnvironmentError: self.addmsg('0001-9', 'failed to open and read file', fn_rules) else: if self.RE_DH_JOIN.search(content): self.debug('Detected use of univention-install-joinscript') try: fn_control = os.path.join(path, 'debian', 'control') parser = uub.ParserDebianControl(fn_control) except uub.UCSLintException: self.debug('Errors in debian/control. Skipping here') else: for binary_package in parser.binary_sections: package = binary_package['Package'] for js in fnlist_joinscripts: if re.match( r'^\./\d\d%s\.u?inst$' % re.escape(package), js): self.debug( 'univention-install-joinscript will take care of %s' % js) fnlist_joinscripts[js] = 0 found[js] = found.get(js, 0) + 1 if self.RE_DH_UMC.search(content): self.debug('Detected use of dh-umc-module-install') for fn in uub.FilteredDirWalkGenerator( debianpath, suffixes=['.umc-modules']): package = os.path.basename(fn)[:-len('.umc-modules')] inst = '%s.inst' % (package, ) uinst = '%s.uinst' % (package, ) for js in fnlist_joinscripts: if js.endswith(inst) or js.endswith(uinst): self.debug( '%s installed by dh-umc-module-install' % (js, )) found[js] = found.get(js, 0) + 1 fnlist_joinscripts[js] = 0 for fn in fnlist: try: content = open(fn, 'r').read() except EnvironmentError: self.addmsg('0001-9', 'failed to open and read file', fn) continue for js in fnlist_joinscripts: name = os.path.basename(js) self.debug('looking for %s in %s' % (name, fn)) if name in content: self.debug('found %s in %s' % (name, fn)) found[js] = found.get(js, 0) + 1 for js in fnlist_joinscripts: if found.get(js, 0) == 0: self.addmsg( '0001-6', 'join script is not mentioned in debian/rules or *.install files', js) # # check if join scripts are present in debian/*{pre,post}{inst,rm} # for f in os.listdir(os.path.join(path, 'debian')): if '.debhelper.' in f: continue if f.endswith('.postinst') or f == 'postinst': bit = CALLED elif f.endswith('.prerm') or f == 'prerm': bit = COPIED elif f.endswith('.postrm') or f == 'postrm': bit = CALLED else: continue fn = os.path.join(path, 'debian', f) self.debug('loading %s' % (fn)) try: content = open(fn, 'r').read() except EnvironmentError: self.addmsg('0001-9', 'failed to open and read file', fn) continue set_e = self.RE_LINE_CONTAINS_SET_E.search(content) if set_e: self.debug('found "set -e" in %s' % fn) for js in fnlist_joinscripts: name = os.path.basename(js) self.debug('looking for %s in %s' % (name, fn)) if name in content: fnlist_joinscripts[js] &= ~bit self.debug('found %s in %s' % (name, fn)) if set_e: for row, line in enumerate(content.splitlines(), start=1): if name in line: match = self.RE_LINE_ENDS_WITH_TRUE.search( line) if not match: self.addmsg( '0001-8', 'the join script %s is not called with "|| true" but "set -e" is set' % (name, ), fn, row, line=line) for js, missing in fnlist_joinscripts.items(): if missing & CALLED and js.endswith('.inst'): self.addmsg( '0001-7', 'Join script is not mentioned in debian/*.postinst', js) if missing & CALLED and js.endswith('.uinst'): self.addmsg( '0001-17', 'Unjoin script seems not to be called in any postrm file', js) if missing & COPIED and js.endswith('.uinst'): self.addmsg( '0001-18', 'Unjoin script seems not to be copied in any prerm file', js)
def check_scripts(self, path: str) -> None: debianpath = join(path, 'debian') version = self.get_debian_version(path) for script_path in uub.FilteredDirWalkGenerator(debianpath, suffixes=self.SCRIPTS): package, suffix = self.split_pkg(script_path) other_scripts = self.SCRIPTS - {suffix} other_actions = set(action for actions in self.ACTIONS.values() for action in actions) - self.ACTIONS[suffix] self.debug('script=%s' % suffix) self.debug('actions=%s' % ' '.join(sorted(self.ACTIONS[suffix]))) self.debug('other_script=%s' % ' '.join(sorted(other_scripts))) self.debug('other_actions=%s' % ' '.join(sorted(other_actions))) with open(script_path, 'r') as script_file: content = script_file.read() for row, line in enumerate(content.splitlines(), start=1): if not line.startswith('#'): break for script_name in other_scripts: if script_name in line: self.addmsg('0018-1', 'wrong script name: %r' % (line.strip(), ), script_path, row, line=line) for row, line in enumerate(content.splitlines(), start=1): if line.startswith('#'): continue for match in self.RE_TEST.finditer(line): try: actions = self.parse_test(split( match.group('cond'))) & other_actions except ValueError as ex: self.debug('Failed %s:%d: %s in %s' % (script_path, row, ex, line)) continue if actions: self.addmsg( '0018-3', 'Invalid actions "%s" in Debian maintainer script' % (','.join(actions), ), script_path, row, line=line) for match in self.RE_COMPARE_VERSIONS.finditer(line): ver_a, op, ver_b = match.groups() for arg in (ver_a, ver_b): if self.RE_ARG2.match(arg): continue if not RE_DEBIAN_PACKAGE_VERSION.match(arg): self.debug("%s:%d: Unknown argument %r" % (script_path, row, arg)) continue ver = Version(arg) self.debug("%s << %s?" % (ver, version)) if ver.numeric and version.numeric and ver.numeric[ 0] < version.numeric[0] - 1: self.addmsg( '0018-5', 'Maintainer script contains old upgrade code for %s << %s' % (ver, version), script_path, row, match.start(0), line) for row, col, match in uub.line_regexp(content, self.RE_CASE): for cases in match.group('cases').split(';;'): cases = cases.lstrip('\t\n\r (') cases = cases.split(')', 1)[0] actions = set(action for case in cases.split('|') for action in split(case)) & other_actions if actions: self.addmsg( '0018-3', 'Invalid actions "%s" in Debian maintainer script' % (','.join(actions), ), script_path, row, col, line=line)
def check(self, path): """ the real check """ super(UniventionPackageCheck, self).check(path) check_files = [] # check if copyright file is missing fn = os.path.join(path, 'debian', 'copyright') if not os.path.exists(fn): self.addmsg('0010-5', 'file is missing', filename=fn) # looking for files below debian/ for f in os.listdir(os.path.join(path, 'debian')): fn = os.path.join(path, 'debian', f) if f.endswith('.preinst') or f.endswith('.postinst') or f.endswith('.prerm') or f.endswith('.postrm') or \ f in [ 'preinst', 'postinst', 'prerm', 'postrm', 'copyright' ]: check_files.append(fn) # looking for python files for fn in uub.FilteredDirWalkGenerator(path, reHashBang=re.compile('^#!'), readSize=100): check_files.append(fn) # Copyright (C) 2004, 2005, 2006 Univention GmbH # Copyright 2008 by reCopyrightVersion = re.compile( 'Copyright(\s+\(C\))?\s+([0-9, -]+)\s+(by|Univention\s+GmbH)') # check files for copyright for fn in check_files: try: content = open(fn, 'r').read() except IOError: self.addmsg('0010-1', 'failed to open and read file', filename=fn) continue self.debug('testing %s' % fn) if 'temporary wrapper script for' in content and 'Generated by ltmain.sh' in content: continue copyright_strings = ( 'under the terms of the GNU Affero General Public License version 3', 'Binary versions of this', 'provided by Univention to you as', 'cryptographic keys etc. are subject to a license agreement between', 'the terms of the GNU AGPL V3', 'You should have received a copy of the GNU Affero General Public', ) for teststr in copyright_strings: if not teststr in content: self.debug('Missing copyright string: %s' % teststr) self.addmsg('0010-2', 'file contains no copyright text block', filename=fn) break else: # copyright text block is present - lets check if it's outdated match = reCopyrightVersion.search(content) if not match: self.addmsg('0010-4', 'cannot find copyright line containing year', filename=fn) else: years = match.group(2) current_year = str(time.localtime()[0]) if not current_year in years: self.debug('Current year=%s years="%s"' % (current_year, years)) self.addmsg('0010-3', 'copyright line seems to be outdated', filename=fn)
def check(self, path): """ the real check """ super(UniventionPackageCheck, self).check(path) fnlist_joinscripts = {} # # search join scripts # for f in os.listdir(path): if f.endswith('.inst') and f[0:2].isdigit(): fn = os.path.join(path, f) fnlist_joinscripts[fn] = False self.debug('found %s' % fn) # # check if join scripts use versioning # for js in fnlist_joinscripts.keys(): self.check_join_script(js) # # check if join scripts are present in debian/rules || debian/*.install # found = {} debianpath = os.path.join(path, 'debian') # get all .install files fnlist = list( uub.FilteredDirWalkGenerator(debianpath, suffixes=['.install'])) # append debian/rules fn_rules = os.path.join(path, 'debian', 'rules') fnlist.append(fn_rules) # Look for dh-umc-modules-install try: content = open(fn_rules, 'r').read() except IOError: self.addmsg('0001-9', 'failed to open and read file', fn_rules) else: if UniventionPackageCheck.RE_DH_JOIN.search(content): self.debug('Detected use of univention-install-joinscript') try: fn_control = os.path.join(path, 'debian', 'control') parser = uub.ParserDebianControl(fn_control) except uub.UCSLintException: self.debug('Errors in debian/control. Skipping here') else: for binary_package in parser.binary_sections: package = binary_package.get('Package') for js in fnlist_joinscripts.keys(): if re.match( r'^\./\d\d%s.inst$' % re.escape(package), js): self.debug( 'univention-install-joinscript will take care of %s' % js) fnlist_joinscripts[js] = True found[js] = found.get(js, 0) + 1 if UniventionPackageCheck.RE_DH_UMC.search(content): self.debug('Detected use of dh-umc-module-install') for fn in uub.FilteredDirWalkGenerator( debianpath, suffixes=['.umc-modules']): package = os.path.basename(fn)[:-len('.umc-modules')] inst = '%s.inst' % (package, ) for js in fnlist_joinscripts.keys(): if js.endswith(inst): self.debug( '%s installed by dh-umc-module-install' % (js, )) found[js] = found.get(js, 0) + 1 fnlist_joinscripts[js] = True for fn in fnlist: try: content = open(fn, 'r').read() except IOError: self.addmsg('0001-9', 'failed to open and read file', fn) for js in fnlist_joinscripts.keys(): name = os.path.basename(js) self.debug('looking for %s in %s' % (name, fn)) if name in content: self.debug('found %s in %s' % (name, fn)) found[js] = found.get(js, 0) + 1 for js in fnlist_joinscripts.keys(): if found.get(js, 0) == 0: self.addmsg( '0001-6', 'join script is not mentioned in debian/rules or *.install files', js) # # check if join scripts are present in debian/*postinst # for f in os.listdir(os.path.join(path, 'debian')): if (f.endswith('.postinst') and not f.endswith('.debhelper.postinst')) or (f == 'postinst'): fn = os.path.join(path, 'debian', f) self.debug('loading %s' % (fn)) try: content = open(fn, 'r').read() except IOError: self.addmsg('0001-9', 'failed to open and read file', fn) continue for js in fnlist_joinscripts.keys(): name = os.path.basename(js) self.debug('looking for %s in %s' % (name, fn)) if name in content: fnlist_joinscripts[js] = True self.debug('found %s in %s' % (name, fn)) match = UniventionPackageCheck.RE_LINE_CONTAINS_SET_E.search( content) if match: self.debug('found "set -e" in %s' % fn) for line in content.splitlines(): if name in line: match = UniventionPackageCheck.RE_LINE_ENDS_WITH_TRUE.search( line) if not match: self.addmsg( '0001-8', 'the join script %s is not called with "|| true" but "set -e" is set' % (name, ), fn) for js, found in fnlist_joinscripts.items(): if not found: self.addmsg( '0001-7', 'Join script is not mentioned in debian/*.postinst', js)
def check(self, path: str) -> None: """ the real check """ super(UniventionPackageCheck, self).check(path) check_files = [] # type: List[str] # check if copyright file is missing fn = os.path.join(path, 'debian', 'copyright') try: with open(fn, 'r') as stream: line = stream.readline().rstrip() if line != DEP5: self.addmsg('0010-6', 'not machine-readable DEP-5', fn) except EnvironmentError: self.addmsg('0010-5', 'file is missing', fn) # looking for files below debian/ for f in os.listdir(os.path.join(path, 'debian')): fn = os.path.join(path, 'debian', f) if f.endswith('.preinst') or f.endswith('.postinst') or f.endswith('.prerm') or f.endswith('.postrm') or \ f in ['preinst', 'postinst', 'prerm', 'postrm', 'copyright']: check_files.append(fn) # looking for python files for fn in uub.FilteredDirWalkGenerator(path, reHashBang=RE_HASHBANG, readSize=100): check_files.append(fn) # check files for copyright for fn in check_files: try: content = open(fn, 'r').read() except (EnvironmentError, UnicodeDecodeError): self.addmsg('0010-1', 'failed to open and read file', fn) continue self.debug('testing %s' % fn) if RE_SKIP.search(content): continue copyright_strings = ( 'under the terms of the GNU Affero General Public License version 3', 'Binary versions of this', 'provided by Univention to you as', 'cryptographic keys etc. are subject to a license agreement between', 'the terms of the GNU AGPL V3', 'You should have received a copy of the GNU Affero General Public', ) for teststr in copyright_strings: if teststr not in content: self.debug('Missing copyright string: %s' % teststr) self.addmsg('0010-2', 'file contains no copyright text block', fn) break else: # copyright text block is present - lets check if it's outdated match = RE_COPYRIGHT_VERSION.search(content) if not match: self.addmsg('0010-4', 'cannot find copyright line containing year', fn) else: years = match.group(1) current_year = str(time.localtime()[0]) if current_year not in years: self.debug('Current year=%s years="%s"' % (current_year, years)) self.addmsg('0010-3', 'copyright line seems to be outdated', fn)