1#!/usr/bin/env python
2#############################################################################
3# Copyright (c) 2015-2018 Balabit
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms of the GNU General Public License version 2 as published
7# by the Free Software Foundation, or (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17#
18# As an additional exemption you are allowed to compile & link against the
19# OpenSSL libraries as published by the OpenSSL project. See the file
20# COPYING for details.
21#
22#############################################################################
23from src.syslog_ng_config.statements.filters.filter import Filter
24
25
26def render_version(version):
27    return "@version: {}\n".format(version)
28
29
30def render_includes(includes):
31    include_lines = ['@include "{}"'.format(include) for include in includes]
32    return "\n".join(include_lines)
33
34
35def render_global_options(global_options):
36    globals_options_header = "options {\n"
37    globals_options_footer = "};\n"
38
39    config_snippet = globals_options_header
40    for option_name, option_value in global_options.items():
41        config_snippet += "    {}({});\n".format(option_name, option_value)
42    config_snippet += globals_options_footer
43
44    return config_snippet
45
46
47def render_positional_options(positional_parameters):
48    config_snippet = ""
49    for parameter in positional_parameters:
50        config_snippet += "        {}\n".format(str(parameter))
51    return config_snippet
52
53
54def render_options(name, options):
55
56    config_snippet = ""
57    config_snippet += "        {}(\n".format(name)
58    config_snippet += render_driver_options(options)
59    config_snippet += "        )\n"
60
61    return config_snippet
62
63
64def render_list(name, options):
65    config_snippet = ""
66
67    for element in options:
68        config_snippet += "        {}({})\n".format(name, element)
69
70    return config_snippet
71
72
73def render_name_value(name, value):
74    return "        {}({})\n".format(name, value)
75
76
77def render_driver(name, driver):
78    return "        {}({})\n".format(name, render_statement(driver))
79
80
81def render_driver_options(driver_options):
82    config_snippet = ""
83
84    for option_name, option_value in driver_options.items():
85        if isinstance(option_value, dict):
86            config_snippet += render_options(option_name, option_value)
87        elif (isinstance(option_value, tuple) or isinstance(option_value, list)):
88            config_snippet += render_list(option_name, option_value)
89        elif isinstance(option_value, Filter):
90            config_snippet += render_driver(option_name, option_value)
91        else:
92            config_snippet += render_name_value(option_name, option_value)
93
94    return config_snippet
95
96
97def render_statement(statement):
98    config_snippet = ""
99    config_snippet += "    {} (\n".format(statement.driver_name)
100    config_snippet += render_positional_options(statement.positional_parameters)
101    config_snippet += render_driver_options(statement.options)
102    config_snippet += "    )"
103
104    return config_snippet
105
106
107def render_statement_groups(statement_groups):
108    config_snippet = ""
109
110    for statement_group in statement_groups:
111        # statement header
112        config_snippet += "\n{} {} {{\n".format(
113            statement_group.group_type, statement_group.group_id,
114        )
115
116        for statement in statement_group:
117            # driver header
118            config_snippet += render_statement(statement)
119
120            # driver footer
121            config_snippet += ";\n"
122
123            # statement footer
124        config_snippet += "};\n"
125
126    return config_snippet
127
128
129def render_logpath_groups(logpath_groups):
130    config_snippet = ""
131
132    for logpath_group in logpath_groups:
133        config_snippet += "\nlog {\n"
134        for statement_group in logpath_group.logpath:
135            if statement_group.group_type == "log":
136                config_snippet += render_logpath_groups(logpath_groups=[statement_group])
137            else:
138                config_snippet += "    {}({});\n".format(
139                    statement_group.group_type, statement_group.group_id,
140                )
141        if logpath_group.flags:
142            config_snippet += "    flags({});\n".format("".join(logpath_group.flags))
143        config_snippet += "};\n"
144
145    return config_snippet
146
147
148class ConfigRenderer(object):
149    def __init__(self, syslog_ng_config):
150        self.__syslog_ng_config = syslog_ng_config
151        self.__syslog_ng_config_content = ""
152        self.__render()
153
154    def get_rendered_config(self):
155        return self.__syslog_ng_config_content
156
157    def __render(self, re_create_config=None):
158
159        version = self.__syslog_ng_config["version"]
160        includes = self.__syslog_ng_config["includes"]
161        global_options = self.__syslog_ng_config["global_options"]
162        statement_groups = self.__syslog_ng_config["statement_groups"]
163        logpath_groups = self.__syslog_ng_config["logpath_groups"]
164
165        config = ""
166
167        if version:
168            config += render_version(version)
169        if includes:
170            config += render_includes(includes)
171        if global_options:
172            config += render_global_options(global_options)
173        if statement_groups:
174            config += render_statement_groups(statement_groups)
175        if logpath_groups:
176            config += render_logpath_groups(logpath_groups)
177
178        if re_create_config:
179            self.__syslog_ng_config_content = config
180        else:
181            self.__syslog_ng_config_content += config
182