Passed
Push — master ( b781e7...0b2115 )
by Matěj
01:22 queued 12s
created

oval_graph.client.Client.open_web_browser()   A

Complexity

Conditions 3

Size

Total Lines 7
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 6.28

Importance

Changes 0
Metric Value
cc 3
eloc 7
nop 2
dl 0
loc 7
ccs 2
cts 7
cp 0.2857
crap 6.28
rs 10
c 0
b 0
f 0
1 1
import re
2 1
import argparse
3 1
import tempfile
4 1
import os
5 1
import webbrowser
6 1
import json
7 1
import shutil
8 1
from datetime import datetime
9 1
import sys
10
11 1
from .xml_parser import XmlParser
12 1
from .converter import Converter
13
14
15 1
class Client():
16 1
    def __init__(self, args):
17 1
        self.parser = None
18 1
        self.arg = self.parse_arguments(args)
19 1
        self.remove_pass_tests = self.arg.remove_pass_tests
20 1
        self.show_fail_rules = self.arg.show_fail_rules
21 1
        self.show_not_selected_rules = self.arg.show_not_selected_rules
22 1
        self.source_filename = self.arg.source_filename
23 1
        self.rule_name = self.arg.rule_id
24 1
        self.out = self.arg.output
25 1
        self.all_rules = self.arg.all
26 1
        self.isatty = sys.stdout.isatty()
27 1
        self.xml_parser = XmlParser(
28
            self.source_filename)
29 1
        if self.remove_pass_tests:
30
            raise NotImplementedError('Not implemented!')
31
32 1
    def run_gui_and_return_answers(self):
33 1
        if self.isatty:
34 1
            if self.all_rules:
35
                return {'rules': [
36
                    rule['id_rule'] for rule in self.search_rules_id()]}
37
            else:
38 1
                try:
39 1
                    import inquirer
40
                    return inquirer.prompt(self.get_questions())
41 1
                except ImportError:
42 1
                    print(self.get_selection_rules())
43 1
                    return None
44
        else:
45
            return {'rules': [
46
                rule['id_rule'] for rule in self.search_rules_id()]}
47
48 1
    def get_list_of_matched_rules(self):
49 1
        rules = self.search_rules_id()
50 1
        if self.show_fail_rules:
51 1
            rules = self._get_only_fail_rule(rules)
52 1
        return rules
53
54 1
    def get_list_of_lines(self):
55 1
        lines = ['== The Rule IDs ==']
56 1
        for rule in self.get_list_of_matched_rules():
57 1
            lines.append("'" + rule['id_rule'] + r'\b' + "'")
58 1
        if self.show_not_selected_rules:
59 1
            for line in self.get_lines_of_wanted_not_selected_rules():
60 1
                lines.append(line)
61 1
        lines.append(
62
            "You haven't got installed inquirer lib. "
63
            "Please copy id rule with you want use and put it in command")
64 1
        return lines
65
66 1
    def get_selection_rules(self):
67 1
        return "\n".join(self.get_list_of_lines())
68
69 1
    def get_lines_of_wanted_not_selected_rules(self):
70 1
        out = []
71 1
        out.append('== The not selected rule IDs ==')
72 1
        for rule in self._get_wanted_not_selected_rules():
73 1
            out.append(rule['id_rule'] + '(Not selected)')
74 1
        return out
75
76 1
    def get_choices(self):
77 1
        rules = self.search_rules_id()
78 1
        if self.show_fail_rules:
79 1
            rules = self._get_only_fail_rule(rules)
80 1
        choices = []
81 1
        for rule in rules:
82 1
            choices.append(rule['id_rule'])
83 1
        if self.show_not_selected_rules:
84 1
            print("\n".join(self.get_lines_of_wanted_not_selected_rules()))
85 1
        return choices
86
87 1
    def get_questions(self):
88 1
        choices = self.get_choices()
89 1
        from inquirer.questions import Checkbox as checkbox
90 1
        questions = [
91
            checkbox(
92
                'rules',
93
                message=(
94
                    "= The Rules IDs = (move - UP and DOWN arrows,"
95
                    " select - SPACE or LEFT and RIGHT arrows, submit - ENTER)"),
96
                choices=choices,
97
            ),
98
        ]
99 1
        return questions
100
101 1
    def _get_only_fail_rule(self, rules):
102 1
        return list(filter(lambda rule: rule['result'] == 'fail', rules))
103
104 1
    def _get_wanted_rules(self):
105 1
        return [
106
            x for x in self.xml_parser.used_rules if re.search(
107
                self.rule_name, x['id_rule'])]
108
109 1
    def _get_wanted_not_selected_rules(self):
110 1
        return [
111
            x for x in self.xml_parser.notselected_rules if re.search(
112
                self.rule_name, x['id_rule'])]
113
114 1
    def create_dict_of_rule(self, rule_id):
115 1
        converter = Converter(self.xml_parser.get_oval_tree(rule_id))
116 1
        return converter.to_JsTree_dict()
117
118 1
    def get_src(self, src):
119 1
        _dir = os.path.dirname(os.path.realpath(__file__))
120 1
        FIXTURE_DIR = os.path.join(_dir, src)
121 1
        return str(FIXTURE_DIR)
122
123 1
    def copy_interpreter(self, dst):
124 1
        src = self.get_src('tree_html_interpreter')
125 1
        os.mkdir(dst)
126 1
        for item in os.listdir(src):
127 1
            s = os.path.join(src, item)
128 1
            d = os.path.join(dst, item)
129 1
            if os.path.isdir(s):
130 1
                shutil.copytree(s, d)
131
            else:
132 1
                shutil.copy2(s, d)
133
134 1
    def open_web_browser(self, src):
135 1
        if not self.off_webbrowser:
136
            src = os.path.join(src, 'index.html')
137
            try:
138
                webbrowser.get('firefox').open_new_tab(src)
139
            except BaseException:
140
                webbrowser.open_new_tab(src)
141
142 1
    def search_rules_id(self):
143 1
        rules = self._get_wanted_rules()
144 1
        notselected_rules = self._get_wanted_not_selected_rules()
145 1
        if len(notselected_rules) and not rules:
146 1
            raise ValueError(
147
                ('err- rule(s) "{}" was not selected, '
148
                 "so there are no results. The rule is"
149
                 ' "notselected" because it'
150
                 " wasn't a part of the executed profile"
151
                 " and therefore it wasn't evaluated "
152
                 "during the scan.")
153
                .format(notselected_rules[0]['id_rule']))
154 1
        elif not notselected_rules and not rules:
155 1
            raise ValueError('err- 404 rule not found!')
156
        else:
157 1
            return rules
158
159 1
    def save_dict(self, dict_, src):
160 1
        with open(os.path.join(src, 'data.js'), "w+") as data_file:
161 1
            data_file.write("var data_json =" + str(json.dumps(
162
                dict_, sort_keys=False, indent=4) + ";"))
163
164 1
    def get_save_src(self, rule):
165 1
        date = str(datetime.now().strftime("-%d_%m_%Y-%H_%M_%S"))
166 1
        if self.out is not None:
167 1
            if not os.path.isdir(self.out):
168 1
                os.mkdir(self.out)
169 1
                return os.path.join(self.out, 'graph-of-' + rule + date)
170
            return os.path.join(
171
                self.out,
172
                'graph-of-' + rule + date)
173 1
        return os.path.join(
174
            os.getcwd(),
175
            'graph-of-' + rule + date)
176
177 1
    def parse_arguments(self, args):
178 1
        self.prepare_parser()
179 1
        args = self.parser.parse_args(args)
180 1
        return args
181
182 1
    def prepare_parser(self):
183 1
        self.parser = argparse.ArgumentParser(
184
            description="Client for visualization of SCAP rule evaluation results")
185 1
        self.parser.add_argument(
186
            '--show-fail-rules',
187
            action="store_true",
188
            default=False,
189
            help="Show only FAIL rules")
190 1
        self.parser.add_argument(
191
            '--show-not-selected-rules',
192
            action="store_true",
193
            default=False,
194
            help="Show notselected rules. These rules will not be visualized.")
195 1
        self.parser.add_argument(
196
            '--output',
197
            action="store",
198
            default=None,
199
            help="The directory where to save output files.")
200 1
        self.parser.add_argument(
201
            '--all',
202
            action="store_true",
203
            default=False,
204
            help="Process all matched rules.")
205 1
        self.parser.add_argument(
206
            '--remove-pass-tests',
207
            action="store_true",
208
            default=False,
209
            help=(
210
                "Do not display passing tests for better orientation in"
211
                " graphs that contain a large amount of nodes.(Not implemented)"))
212 1
        self.parser.add_argument("source_filename", help="ARF scan file")
213 1
        self.parser.add_argument(
214
            "rule_id", help=(
215
                "Rule ID to be visualized. A part from the full rule ID"
216
                " a part of the ID or a regular expression can be used."
217
                " If brackets are used in the regular expression "
218
                "the regular expression must be quoted."))
219