Source code for stix2patterns.validator
"""
Validates a user entered pattern against STIXPattern grammar.
"""
from __future__ import print_function
import argparse
from antlr4 import InputStream
import six
from . import DEFAULT_VERSION
from .exceptions import STIXPatternErrorListener # noqa: F401
from .helpers import brackets_check
from .v20.validator import run_validator as run_validator20
from .v21.validator import run_validator as run_validator21
[docs]def run_validator(pattern, stix_version=DEFAULT_VERSION):
"""
Validates a pattern against the STIX Pattern grammar. Error messages are
returned in a list. The test passed if the returned list is empty.
"""
if isinstance(pattern, six.string_types):
pattern_str = pattern
pattern = InputStream(pattern)
else:
pattern_str = pattern.readline()
pattern.seek(0)
if stix_version == '2.1':
err_messages = run_validator21(pattern)
else:
err_messages = run_validator20(pattern)
if not brackets_check(pattern_str):
err_messages.insert(
0,
"FAIL: Error found at line 1:0. input is missing square brackets"
)
return err_messages
[docs]def validate(user_input, stix_version=DEFAULT_VERSION, ret_errs=False, print_errs=False):
"""
Wrapper for run_validator function that returns True if the user_input
contains a valid STIX pattern or False otherwise. The error messages may
also be returned or printed based upon the ret_errs and print_errs arg
values.
"""
errs = run_validator(user_input, stix_version)
passed = len(errs) == 0
if print_errs:
for err in errs:
print(err)
if ret_errs:
return passed, errs
return passed
[docs]def main():
"""
Continues to validate patterns until it encounters EOF within a pattern
file or Ctrl-C is pressed by the user.
"""
parser = argparse.ArgumentParser(description='Validate STIX Patterns.')
parser.add_argument('-f', '--file',
help="Specify this arg to read patterns from a file.",
type=argparse.FileType("r"))
parser.add_argument('-v', '--version',
default=DEFAULT_VERSION,
help="Specify version of STIX 2 specification to validate against.")
args = parser.parse_args()
pass_count = fail_count = 0
# I tried using a generator (where each iteration would run raw_input()),
# but raw_input()'s behavior seems to change when called from within a
# generator: I only get one line, then the generator completes! I don't
# know why behavior changes...
import functools
if args.file:
nextpattern = args.file.readline
else:
nextpattern = functools.partial(six.moves.input, "Enter a pattern to validate: ")
try:
while True:
pattern = nextpattern()
if not pattern:
break
tests_passed, err_strings = validate(pattern, args.version, True)
if tests_passed:
print("\nPASS: %s" % pattern)
pass_count += 1
else:
for err in err_strings:
print(err, '\n')
fail_count += 1
except (EOFError, KeyboardInterrupt):
pass
finally:
if args.file:
args.file.close()
print("\nPASSED:", pass_count, " patterns")
print("FAILED:", fail_count, " patterns")
if __name__ == '__main__':
main()