diff --git a/swh/web/ui/query.py b/swh/web/ui/query.py index 08d41117..ac795517 100644 --- a/swh/web/ui/query.py +++ b/swh/web/ui/query.py @@ -1,59 +1,58 @@ # Copyright (C) 2015 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import re from swh.core.hashutil import ALGORITHMS, hex_to_hash from swh.web.ui.exc import BadInputExc SHA256_RE = re.compile(r'^[0-9a-f]{64}$', re.IGNORECASE) SHA1_RE = re.compile(r'^[0-9a-f]{40}$', re.IGNORECASE) def parse_hash(q): """Detect the hash type of a user submitted query string. Args: query string with the following format: "[HASH_TYPE:]HEX_CHECKSUM", where HASH_TYPE is optional, defaults to "sha1", and can be one of swh.core.hashutil.ALGORITHMS Returns: A pair (hash_algorithm, byte hash value) Raises: ValueError if the given query string does not correspond to a valid hash value """ def guess_algo(q): if SHA1_RE.match(q): return 'sha1' elif SHA256_RE.match(q): return 'sha256' else: raise BadInputExc('Invalid checksum query string %s' % q) def check_algo(algo, hex): - if (algo in set(['sha1', 'sha1_git']) and not SHA1_RE.match(hex)) \ + if (algo in {'sha1', 'sha1_git'} and not SHA1_RE.match(hex)) \ or (algo == 'sha256' and not SHA256_RE.match(hex)): raise BadInputExc('Invalid hash %s for algorithm %s' % (hex, algo)) parts = q.split(':') if len(parts) > 2: raise BadInputExc('Invalid checksum query string %s' % q) elif len(parts) == 1: parts = (guess_algo(q), q) elif len(parts) == 2: check_algo(parts[0], parts[1]) - algo = parts[0] - hash = hex_to_hash(parts[1]) + algo = parts[0] if algo not in ALGORITHMS: raise BadInputExc('Unknown hash algorithm %s' % algo) - return (algo, hash) + return (algo, hex_to_hash(parts[1])) diff --git a/swh/web/ui/tests/test_query.py b/swh/web/ui/tests/test_query.py index 3158e20d..53dfa039 100644 --- a/swh/web/ui/tests/test_query.py +++ b/swh/web/ui/tests/test_query.py @@ -1,34 +1,75 @@ # Copyright (C) 2015 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import unittest from nose.tools import istest from swh.core import hashutil from swh.web.ui import query from swh.web.ui.exc import BadInputExc class QueryTestCase(unittest.TestCase): + @istest + def parse_hash_malformed_query_with_more_than_2_parts(self): + with self.assertRaises(BadInputExc): + query.parse_hash('sha1:1234567890987654:other-stuff') @istest - def parse_hash(self): - q = 'f1d2d2f924e986ac86fdf7b36c94bcdf32beec15' - r = query.parse_hash(q) - self.assertEquals(r, ('sha1', hashutil.hex_to_hash(q))) + def parse_hash_guess_sha1(self): + h = 'f1d2d2f924e986ac86fdf7b36c94bcdf32beec15' + r = query.parse_hash(h) + self.assertEquals(r, ('sha1', hashutil.hex_to_hash(h))) @istest - def parse_hash_2(self): - q = '084C799CD551DD1D8D5C5F9A5D593B2' \ + def parse_hash_guess_sha256(self): + h = '084C799CD551DD1D8D5C5F9A5D593B2' \ 'E931F5E36122ee5c793c1d08a19839cc0' - r = query.parse_hash(q) - self.assertEquals(r, ('sha256', hashutil.hex_to_hash(q))) + r = query.parse_hash(h) + self.assertEquals(r, ('sha256', hashutil.hex_to_hash(h))) + + @istest + def parse_hash_guess_algo_malformed_hash(self): + with self.assertRaises(BadInputExc): + query.parse_hash('1234567890987654') + + @istest + def parse_hash_check_sha1(self): + h = 'f1d2d2f924e986ac86fdf7b36c94bcdf32beec15' + r = query.parse_hash('sha1:' + h) + self.assertEquals(r, ('sha1', hashutil.hex_to_hash(h))) + + @istest + def parse_hash_check_sha1_git(self): + h = 'e1d2d2f924e986ac86fdf7b36c94bcdf32beec15' + r = query.parse_hash('sha1_git:' + h) + self.assertEquals(r, ('sha1_git', hashutil.hex_to_hash(h))) + + @istest + def parse_hash_check_sha256(self): + h = '084C799CD551DD1D8D5C5F9A5D593B2E931F5E36122ee5c793c1d08a19839cc0' + r = query.parse_hash('sha256:' + h) + self.assertEquals(r, ('sha256', hashutil.hex_to_hash(h))) + + @istest + def parse_hash_check_algo_malformed_sha1_hash(self): + with self.assertRaises(BadInputExc): + query.parse_hash('sha1:1234567890987654') + + @istest + def parse_hash_check_algo_malformed_sha1_git_hash(self): + with self.assertRaises(BadInputExc): + query.parse_hash('sha1_git:1234567890987654') + + @istest + def parse_hash_check_algo_malformed_sha256_hash(self): + with self.assertRaises(BadInputExc): + query.parse_hash('sha256:1234567890987654') @istest - def parse_hash_3(self): - q = '1234567890987654' + def parse_hash_check_algo_unknown_one(self): with self.assertRaises(BadInputExc): - query.parse_hash(q) + query.parse_hash('sha2:1234567890987654')