1 /*
2 * Copyright (c) 2020 Balabit
3 * Copyright (c) 2020 Balazs Scheidler <bazsi77@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * As an additional exemption you are allowed to compile & link against the
20 * OpenSSL libraries as published by the OpenSSL project. See the file
21 * COPYING for details.
22 *
23 */
24
25 #include "eval.h"
26 #include "repr.h"
27 #include "macros.h"
28 #include "escaping.h"
29 #include "cfg.h"
30
31 void
log_template_append_format_with_context(LogTemplate * self,LogMessage ** messages,gint num_messages,LogTemplateEvalOptions * options,GString * result)32 log_template_append_format_with_context(LogTemplate *self, LogMessage **messages, gint num_messages,
33 LogTemplateEvalOptions *options, GString *result)
34 {
35 GList *p;
36 LogTemplateElem *e;
37
38 if (!options->opts)
39 options->opts = &self->cfg->template_options;
40
41 for (p = self->compiled_template; p; p = g_list_next(p))
42 {
43 gint msg_ndx;
44
45 e = (LogTemplateElem *) p->data;
46 if (e->text)
47 {
48 g_string_append_len(result, e->text, e->text_len);
49 }
50
51 /* NOTE: msg_ref is 1 larger than the index specified by the user in
52 * order to make it distinguishable from the zero value. Therefore
53 * the '>' instead of '>='
54 *
55 * msg_ref == 0 means that the user didn't specify msg_ref
56 * msg_ref >= 1 means that the user supplied the given msg_ref, 1 is equal to @0 */
57 if (e->msg_ref > num_messages)
58 continue;
59 msg_ndx = num_messages - e->msg_ref;
60
61 /* value and macro can't understand a context, assume that no msg_ref means @0 */
62 if (e->msg_ref == 0)
63 msg_ndx--;
64
65 switch (e->type)
66 {
67 case LTE_VALUE:
68 {
69 const gchar *value = NULL;
70 gssize value_len = -1;
71
72 value = log_msg_get_value(messages[msg_ndx], e->value_handle, &value_len);
73 if (value && value[0])
74 result_append(result, value, value_len, self->escape);
75 else if (e->default_value)
76 result_append(result, e->default_value, -1, self->escape);
77 break;
78 }
79 case LTE_MACRO:
80 {
81 gint len = result->len;
82
83 if (e->macro)
84 {
85 log_macro_expand(result, e->macro, self->escape, options, messages[msg_ndx]);
86 if (len == result->len && e->default_value)
87 g_string_append(result, e->default_value);
88 }
89 break;
90 }
91 case LTE_FUNC:
92 {
93 if (1)
94 {
95 LogTemplateInvokeArgs args =
96 {
97 e->msg_ref ? &messages[msg_ndx] : messages,
98 e->msg_ref ? 1 : num_messages,
99 options,
100 };
101
102
103 /* if a function call is called with an msg_ref, we only
104 * pass that given logmsg to argument resolution, otherwise
105 * we pass the whole set so the arguments can individually
106 * specify which message they want to resolve from
107 */
108 if (e->func.ops->eval)
109 e->func.ops->eval(e->func.ops, e->func.state, &args);
110 e->func.ops->call(e->func.ops, e->func.state, &args, result);
111 }
112 break;
113 }
114 default:
115 g_assert_not_reached();
116 break;
117 }
118 }
119 }
120
121 void
log_template_format_with_context(LogTemplate * self,LogMessage ** messages,gint num_messages,LogTemplateEvalOptions * options,GString * result)122 log_template_format_with_context(LogTemplate *self, LogMessage **messages, gint num_messages,
123 LogTemplateEvalOptions *options, GString *result)
124 {
125 g_string_truncate(result, 0);
126 log_template_append_format_with_context(self, messages, num_messages, options, result);
127 }
128
129 void
log_template_append_format(LogTemplate * self,LogMessage * lm,LogTemplateEvalOptions * options,GString * result)130 log_template_append_format(LogTemplate *self, LogMessage *lm, LogTemplateEvalOptions *options, GString *result)
131 {
132 log_template_append_format_with_context(self, &lm, 1, options, result);
133 }
134
135 void
log_template_format(LogTemplate * self,LogMessage * lm,LogTemplateEvalOptions * options,GString * result)136 log_template_format(LogTemplate *self, LogMessage *lm, LogTemplateEvalOptions *options, GString *result)
137 {
138 g_string_truncate(result, 0);
139 log_template_append_format(self, lm, options, result);
140 }
141