Skip to content

Commit

Permalink
Merge branch 'master' into nonstrict-encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
buglloc authored May 16, 2017
2 parents cea880b + 39fa26c commit cb4dbc8
Show file tree
Hide file tree
Showing 20 changed files with 128 additions and 87 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
language: python
sudo: false
python:
- "2.6"
- "2.7"
- "3.5"
- "3.6"
Expand All @@ -11,4 +12,4 @@ install:

script:
- nosetests --with-coverage --cover-package gixy -v
- flake8 --max-line-length=120 setup.py yodax
- if [[ $TRAVIS_PYTHON_VERSION != '2.6' ]]; then flake8 --max-line-length=120 setup.py gixy; fi
4 changes: 2 additions & 2 deletions docs/en/plugins/addheadermultiline.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# [add_header_multiline] Multiline response headers

You should avoid using multiline response headers, because:
* they are depricated (see [RFC 7230](https://tools.ietf.org/html/rfc7230#section-3.2.4));
* they are deprecated (see [RFC 7230](https://tools.ietf.org/html/rfc7230#section-3.2.4));
* some HTTP-clients and web browser never supported them (e.g. IE/Edge/Nginx).

## How can I find it?
Expand All @@ -22,4 +22,4 @@ more_set_headers -t 'text/html text/plain'
```

## What can I do?
The only solution is to never use multiline response headers.
The only solution is to never use multiline response headers.
2 changes: 1 addition & 1 deletion gixy/cli/argparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def get_possible_config_keys(self, action):
"""
keys = []
for arg in action.option_strings:
if arg in {'--config', '--write-config', '--version'}:
if arg in ['--config', '--write-config', '--version']:
continue
if any([arg.startswith(2 * c) for c in self.prefix_chars]):
keys += [arg[2:], arg] # eg. for '--bla' return ['bla', '--bla']
Expand Down
9 changes: 4 additions & 5 deletions gixy/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
def _init_logger(debug=False):
LOG.handlers = []
log_level = logging.DEBUG if debug else logging.INFO
logging.captureWarnings(True)

LOG.setLevel(log_level)
handler = logging.StreamHandler(sys.stderr)
Expand All @@ -31,7 +30,7 @@ def _create_plugin_help(option):
else:
default = str(option)

return 'Default: {}'.format(default)
return 'Default: {0}'.format(default)


def _get_cli_parser():
Expand All @@ -41,7 +40,7 @@ def _get_cli_parser():

parser.add_argument(
'-v', '--version', action='version',
version='Gixy v{}'.format(gixy.version))
version='Gixy v{0}'.format(gixy.version))

parser.add_argument(
'-l', '--level', dest='level', action='count', default=0,
Expand Down Expand Up @@ -106,7 +105,7 @@ def main():
try:
severity = gixy.severity.ALL[args.level]
except IndexError:
sys.stderr.write('Too high level filtering. Maximum level: -{}\n'.format('l' * (len(gixy.severity.ALL) - 1)))
sys.stderr.write('Too high level filtering. Maximum level: -{0}\n'.format('l' * (len(gixy.severity.ALL) - 1)))
sys.exit(1)

if args.tests:
Expand All @@ -132,7 +131,7 @@ def main():
name = plugin_cls.__name__
options = copy.deepcopy(plugin_cls.options)
for opt_key, opt_val in options.items():
option_name = '{}:{}'.format(name, opt_key)
option_name = '{name}:{key}'.format(name=name, key=opt_key)
if option_name not in args:
continue

Expand Down
2 changes: 1 addition & 1 deletion gixy/core/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def get_var(self, name):
result = builtins.builtin_var(name)

if not result:
LOG.info("Can't find variable '{}'".format(name))
LOG.info("Can't find variable '{0}'".format(name))
return result

def __deepcopy__(self, memo):
Expand Down
10 changes: 5 additions & 5 deletions gixy/core/regexp.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ def _parse(self):
elif isinstance(token, sre_parse.SubPattern):
self.childs.append(InternalSubpatternToken(token=token, parent=self.parent, regexp=self.regexp))
else:
raise RuntimeError('Unexpected token {} in branch'.format(token))
raise RuntimeError('Unexpected token {0} in branch'.format(token))

def can_contain(self, char, skip_literal=True):
for child in self.childs:
Expand Down Expand Up @@ -461,7 +461,7 @@ def generate(self, context):
return res

def __str__(self):
return '(?:{})'.format('|'.join(str(x) for x in self.childs))
return '(?:{0})'.format('|'.join(str(x) for x in self.childs))


class SubpatternToken(Token):
Expand Down Expand Up @@ -661,7 +661,7 @@ def _generate_negative(self, context):
elif isinstance(child, CategoryToken):
blacklisted.update(child.char_list)
else:
LOG.info('Unexpected child "{!r}"'.format(child))
LOG.info('Unexpected child "{0!r}"'.format(child))

for char in _build_reverse_list(set()):
if char not in blacklisted:
Expand Down Expand Up @@ -756,7 +756,7 @@ def generate(self, context):
return self.group.generate(context)

def __str__(self):
return '\\\\{}'.format(self.id)
return '\\\\{0}'.format(self.id)


class AssertToken(Token):
Expand Down Expand Up @@ -854,7 +854,7 @@ def parse(sre_obj, parent=None, regexp=None):
elif token[0] == sre_parse.ASSERT_NOT:
pass # TODO(buglloc): Do it!
else:
LOG.info('Unexpected token "{}"'.format(token[0]))
LOG.info('Unexpected token "{0}"'.format(token[0]))

return result

Expand Down
10 changes: 5 additions & 5 deletions gixy/directives/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def append(self, directive):
self.children.append(directive)

def __str__(self):
return '{} {} {}'.format(self.name, ' '.join(self.args), '{')
return '{name} {args} {{'.format(name=self.name, args=' '.join(self.args))


class Root(Block):
Expand Down Expand Up @@ -89,7 +89,7 @@ def get_names(self):
def __str__(self):
server_names = [str(sn) for sn in self.find('server_name')]
if server_names:
return 'server {{\n{}'.format('\n'.join(server_names[:2]))
return 'server {{\n{0}'.format('\n'.join(server_names[:2]))
return 'server {'


Expand Down Expand Up @@ -141,10 +141,10 @@ def __init__(self, name, args):
# if ($request_method = POST)
self.variable, self.operand, self.value = args
else:
raise Exception('Unknown "if" definition, args: {}'.format(repr(args)))
raise Exception('Unknown "if" definition, args: {0!r}'.format(args))

def __str__(self):
return '{} ({}) {{'.format(self.name, ' '.join(self.args))
return '{name} ({args}) {{'.format(name=self.name, args=' '.join(self.args))


class IncludeBlock(Block):
Expand All @@ -156,7 +156,7 @@ def __init__(self, name, args):
self.file_path = args[0]

def __str__(self):
return 'include {};'.format(self.file_path)
return 'include {0};'.format(self.file_path)


class MapBlock(Block):
Expand Down
2 changes: 1 addition & 1 deletion gixy/directives/directive.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def variables(self):
raise NotImplementedError()

def __str__(self):
return '{} {};'.format(self.name, ' '.join(self.args))
return '{name} {args};'.format(name=self.name, args=' '.join(self.args))


class AddHeaderDirective(Directive):
Expand Down
6 changes: 3 additions & 3 deletions gixy/formatters/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


class BaseFormatter(object):
skip_parents = {block.Root, block.HttpBlock}
skip_parents = set([block.Root, block.HttpBlock])

def format_reports(self, reports, stats):
raise NotImplementedError("Formatter must override format_reports function")
Expand Down Expand Up @@ -74,11 +74,11 @@ def _traverse_tree(self, tree, points, level):
if leap.is_block:
result.append('')
directive = str(leap).replace('\n', '\n' + '\t' * (level + 1))
result.append('{:s}{:s}'.format('\t' * level, directive))
result.append('{indent:s}{dir:s}'.format(indent='\t' * level, dir=directive))

if leap.is_block:
result.extend(self._traverse_tree(leap, points, level + 1 if printable else level))
if printable and have_parentheses:
result.append('{:s}}}'.format('\t' * level))
result.append('{indent:s}}}'.format(indent='\t' * level))

return result
10 changes: 5 additions & 5 deletions gixy/parser/nginx_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ def __init__(self, cwd='', allow_includes=True):
self._init_directives()

def parse_file(self, path, root=None):
LOG.debug("Parse file: {}".format(path))
content = open(path, mode='rb').read()
LOG.debug("Parse file: {0}".format(path))
content = open(path).read()
return self.parse(content=content, root=root, path_info=path)

def parse(self, content, root=None, path_info=None):
Expand Down Expand Up @@ -103,7 +103,7 @@ def _resolve_include(self, args, parent):
if self.is_dump:
return self._resolve_dump_include(pattern=pattern, parent=parent)
if not self.allow_includes:
LOG.debug('Includes are disallowed, skip: {}'.format(pattern))
LOG.debug('Includes are disallowed, skip: {0}'.format(pattern))
return

return self._resolve_file_include(pattern=pattern, parent=parent)
Expand All @@ -117,7 +117,7 @@ def _resolve_file_include(self, pattern, parent):
self.parse_file(file_path, include)

if not file_path:
LOG.warning("File not found: {}".format(path))
LOG.warning("File not found: {0}".format(path))

def _resolve_dump_include(self, pattern, parent):
path = os.path.join(self.cwd, pattern)
Expand All @@ -130,7 +130,7 @@ def _resolve_dump_include(self, pattern, parent):
self.parse_block(parsed, include)

if not founded:
LOG.warning("File not found: {}".format(path))
LOG.warning("File not found: {0}".format(path))

def _prepare_dump(self, parsed_block):
filename = ''
Expand Down
2 changes: 1 addition & 1 deletion gixy/plugins/add_header_multiline.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def get_header_values(directive):
result = []
skip_next = False
for arg in directive.args:
if arg in {'-s', '-t'}:
if arg in ['-s', '-t']:
# Skip next value, because it's not a header
skip_next = True
elif arg.startswith('-'):
Expand Down
10 changes: 5 additions & 5 deletions gixy/plugins/add_header_redefinition.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ class add_header_redefinition(Plugin):
'See documentation: http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header')
help_url = 'https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheaderredefinition.md'
directives = ['server', 'location', 'if']
options = {'headers': {'x-frame-options',
'x-content-type-options',
'x-xss-protection',
'content-security-policy',
'cache-control'}
options = {'headers': set(['x-frame-options',
'x-content-type-options',
'x-xss-protection',
'content-security-policy',
'cache-control'])
}

def __init__(self, config):
Expand Down
6 changes: 3 additions & 3 deletions gixy/plugins/origins.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,16 @@ def __init__(self, config):
self.valid_re = re.compile(regex)

def audit(self, directive):
if directive.operand not in {'~', '~*', '!~', '!~*'}:
if directive.operand not in ['~', '~*', '!~', '!~*']:
# Not regexp
return

if directive.variable not in {'$http_referer', '$http_origin'}:
if directive.variable not in ['$http_referer', '$http_origin']:
# Not interesting
return

invalid_referers = set()
regexp = Regexp(directive.value, case_sensitive=(directive.operand in {'~', '!~'}))
regexp = Regexp(directive.value, case_sensitive=(directive.operand in ['~', '!~']))
for value in regexp.generate('/', anchored=True):
if value.startswith('^'):
value = value[1:]
Expand Down
36 changes: 36 additions & 0 deletions tests/asserts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from nose.tools import assert_true, assert_false


'''
Various nose.tools helpers that doesn't exists in Python 2.6 Unittest :(
Must be removed with drop Python 2.6 support
'''


def assert_is_instance(obj, cls, msg=None):
"""Same as assert_true(isinstance(obj, cls)), with a nicer
default message."""
if not msg:
msg = '{orig} is not an instance of {test}'.format(orig=type(obj), test=cls)
assert_true(isinstance(obj, cls), msg=msg)


def assert_is_none(obj, msg=None):
"""Same as assert_true(obj is None), with a nicer default message."""
if not msg:
msg = '{orig!r} is not None'.format(orig=obj)
assert_true(obj is None, msg=msg)


def assert_is_not_none(obj, msg=None):
"""Same as assert_false(obj is None), with a nicer default message."""
if not msg:
msg = '{orig!r} is None'.format(orig=obj)
assert_false(obj is None, msg=msg)


def assert_in(member, container, msg=None):
"""Just like assert_true(a in b), but with a nicer default message."""
if not msg:
msg = '{member!r} not found in {container!r}'.format(member=member, container=container)
assert_true(member in container, msg=msg)
Loading

0 comments on commit cb4dbc8

Please sign in to comment.