| # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Define a stateless pattern for validating url query parameters (?k=v&k=v...). |
| |
| The common Validate function accepts a list of xValidator classes against |
| which the request will be checked. The xValidator classes must each |
| include the following class variables: required, supported and |
| match_patterns. |
| |
| Note, Django request objects support multiple instances of a query |
| parameter in an url. |
| e.g. http:/x/y?mykey=foo&mykey=bar ==> {'mykey': ['foo', 'bar'] |
| """ |
| |
| |
| import re |
| |
| from autotest_lib.frontend.croschart.charterrors import ChartInputError |
| |
| |
| BOOL_PATTERN = re.compile('((?i)(true|false)$)') |
| BUILD_PATTERN1 = re.compile('([\d]+\.[\d]+\.[\d]+\.[\d]+$)') |
| BUILD_PATTERN2 = re.compile('(R[\d]+-[\d]+\.[\d]+\.[\d]+$)') |
| DATE_PATTERN = re.compile('([\d]{4}-[\d]{1,2}-[\d]{1,2}$)') |
| DIM_PATTERN = re.compile('([\d]+$)') |
| INTERVAL_PATTERN = re.compile('([\d]+\,(?i)(day|week|month)$)') |
| TESTKEY_PATTERN = re.compile('([\w\.]+,[\w\.\,-]+$)') |
| |
| |
| def Validate(request, validator_list): |
| """Run through the parameter validations.""" |
| for validator in validator_list: |
| for p in validator.supported: |
| value_list = request.GET.getlist(p) |
| # Required parameters must be provided. |
| if p in validator.required and not value_list: |
| raise ChartInputError("Parameter '%s' is required." % p) |
| if not p in request.GET: |
| continue |
| # Do not allow any empty parameter values. |
| if '' in value_list: |
| raise ChartInputError("Parameter '%s' cannot be empty." % p) |
| # Check format where supplied. |
| patterns = validator.match_patterns.get(p, None) |
| if patterns: |
| for v in value_list: |
| found = False |
| for pattern in patterns: |
| if re.match(pattern, v): |
| found = True |
| break |
| if not found: |
| raise ChartInputError("Parameter '%s' is improperly formatted." % p) |
| |
| |
| class CrosChartValidator(object): |
| """Common parameter expectations for Chrome OS charts.""" |
| |
| required = ['board', 'system', 'testkey'] |
| supported = required + ['width', 'height', 'chromeversion', 'updatecache'] |
| match_patterns = {'testkey': [TESTKEY_PATTERN], 'width': [DIM_PATTERN], |
| 'height': [DIM_PATTERN], 'chromeversion': [BOOL_PATTERN], |
| 'updatecache': [BOOL_PATTERN]} |
| |
| |
| class CrosPlatformsValidator(object): |
| """Common parameter expectations for Chrome OS platforms reports.""" |
| |
| required = ['platform'] |
| supported = required + ['testkey', 'width', 'height', 'chromeversion', |
| 'updatecache'] |
| match_patterns = {'testkey': [TESTKEY_PATTERN], 'width': [DIM_PATTERN], |
| 'height': [DIM_PATTERN], 'chromeversion': [BOOL_PATTERN], |
| 'updatecache': [BOOL_PATTERN]} |
| |
| |
| class CrosReportValidator(object): |
| """Common parameter expectations for Chrome OS reports.""" |
| |
| required = ['board', 'system'] |
| supported = required + ['testkey', 'width', 'height', 'chromeversion', |
| 'updatecache'] |
| match_patterns = {'testkey': [TESTKEY_PATTERN], 'width': [DIM_PATTERN], |
| 'height': [DIM_PATTERN], 'chromeversion': [BOOL_PATTERN], |
| 'updatecache': [BOOL_PATTERN]} |
| |
| |
| class BuildRangeValidator(object): |
| """Chrome OS build range URL parameters.""" |
| |
| required = ['from_build', 'to_build'] |
| supported = required |
| match_patterns = {'from_build': [BUILD_PATTERN1, BUILD_PATTERN2], |
| 'to_build': [BUILD_PATTERN1, BUILD_PATTERN2]} |
| |
| |
| class DateRangeValidator(object): |
| """Chrome OS date range URL parameters.""" |
| |
| required = ['from_date', 'to_date'] |
| supported = required |
| match_patterns = {'from_date': [DATE_PATTERN], 'to_date': [DATE_PATTERN]} |
| |
| |
| class IntervalRangeValidator(object): |
| """Chrome OS interval range URL parameters.""" |
| |
| required = ['interval'] |
| supported = required |
| match_patterns = {'interval': [INTERVAL_PATTERN]} |
| |