1# See utils/checkpackagelib/readme.txt before editing this file.
2# The validity of the hashes itself is checked when building, so below check
3# functions don't need to check for things already checked by running
4# "make package-dirclean package-source".
5
6import re
7
8from checkpackagelib.base import _CheckFunction
9from checkpackagelib.lib import ConsecutiveEmptyLines  # noqa: F401
10from checkpackagelib.lib import EmptyLastLine          # noqa: F401
11from checkpackagelib.lib import NewlineAtEof           # noqa: F401
12from checkpackagelib.lib import TrailingSpace          # noqa: F401
13from checkpackagelib.tool import NotExecutable         # noqa: F401
14
15
16def _empty_line_or_comment(text):
17    return text.strip() == "" or text.startswith("#")
18
19
20class HashNumberOfFields(_CheckFunction):
21    def check_line(self, lineno, text):
22        if _empty_line_or_comment(text):
23            return
24
25        fields = text.split()
26        if len(fields) != 3:
27            return ["{}:{}: expected three fields ({}#adding-packages-hash)"
28                    .format(self.filename, lineno, self.url_to_manual),
29                    text]
30
31
32class HashType(_CheckFunction):
33    len_of_hash = {"md5": 32, "sha1": 40, "sha224": 56, "sha256": 64,
34                   "sha384": 96, "sha512": 128}
35
36    def check_line(self, lineno, text):
37        if _empty_line_or_comment(text):
38            return
39
40        fields = text.split()
41        if len(fields) < 2:
42            return
43
44        htype, hexa = fields[:2]
45        if htype not in self.len_of_hash.keys():
46            return ["{}:{}: unexpected type of hash ({}#adding-packages-hash)"
47                    .format(self.filename, lineno, self.url_to_manual),
48                    text]
49        if not re.match("^[0-9A-Fa-f]{%s}$" % self.len_of_hash[htype], hexa):
50            return ["{}:{}: hash size does not match type "
51                    "({}#adding-packages-hash)"
52                    .format(self.filename, lineno, self.url_to_manual),
53                    text,
54                    "expected {} hex digits".format(self.len_of_hash[htype])]
55
56
57class HashSpaces(_CheckFunction):
58    def check_line(self, lineno, text):
59        if _empty_line_or_comment(text):
60            return
61
62        fields = text.split()
63        if len(fields) != 3:
64            # Handled by HashNumberOfFields
65            return
66
67        if not re.match(re.escape("{}  {}  {}".format(*fields)), text):
68            return ["{}:{}: separation does not match expectation "
69                    "({}#adding-packages-hash)"
70                    .format(self.filename, lineno, self.url_to_manual), text]
71