1 /*
2  * Copyright (c) 2015 Balabit
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 as published
6  * by the Free Software Foundation, or (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16  *
17  * As an additional exemption you are allowed to compile & link against the
18  * OpenSSL libraries as published by the OpenSSL project. See the file
19  * COPYING for details.
20  *
21  */
22 
23 #include "format-welf.h"
24 #include "utf8utils.h"
25 #include "value-pairs/cmdline.h"
26 
27 typedef struct _TFWelfState
28 {
29   TFSimpleFuncState super;
30   ValuePairs *vp;
31 } TFWelfState;
32 
33 typedef struct _TFWelfIterState
34 {
35   GString *result;
36   gboolean initial_kv_pair_printed;
37 } TFWelfIterState;
38 
39 static gboolean
tf_format_welf_prepare(LogTemplateFunction * self,gpointer s,LogTemplate * parent,gint argc,gchar * argv[],GError ** error)40 tf_format_welf_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent,
41                        gint argc, gchar *argv[],
42                        GError **error)
43 {
44   TFWelfState *state = (TFWelfState *) s;
45 
46   state->vp = value_pairs_new_from_cmdline (parent->cfg, &argc, &argv, FALSE, error);
47   if (!state->vp)
48     return FALSE;
49 
50   return TRUE;
51 }
52 
53 static gboolean
tf_format_welf_foreach(const gchar * name,TypeHint type,const gchar * value,gsize value_len,gpointer user_data)54 tf_format_welf_foreach(const gchar *name, TypeHint type, const gchar *value,
55                        gsize value_len, gpointer user_data)
56 {
57   TFWelfIterState *iter_state = (TFWelfIterState *) user_data;
58   GString *result = iter_state->result;
59 
60   if (iter_state->initial_kv_pair_printed)
61     g_string_append(result, " ");
62   else
63     iter_state->initial_kv_pair_printed = TRUE;
64 
65   g_string_append(result, name);
66   g_string_append_c(result, '=');
67   if (memchr(value, ' ', value_len) == NULL)
68     append_unsafe_utf8_as_escaped_binary(result, value, value_len, NULL);
69   else
70     {
71       g_string_append_c(result, '"');
72       append_unsafe_utf8_as_escaped_binary(result, value, value_len, "\"");
73       g_string_append_c(result, '"');
74     }
75 
76   return FALSE;
77 }
78 
79 static gint
tf_format_welf_strcmp(gconstpointer a,gconstpointer b)80 tf_format_welf_strcmp(gconstpointer a, gconstpointer b)
81 {
82   gchar *sa = (gchar *)a, *sb = (gchar *)b;
83   if (strcmp (sa, "id") == 0)
84     return -1;
85   return strcmp(sa, sb);
86 }
87 
88 static void
tf_format_welf_call(LogTemplateFunction * self,gpointer s,const LogTemplateInvokeArgs * args,GString * result)89 tf_format_welf_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result)
90 {
91   TFWelfState *state = (TFWelfState *) s;
92   TFWelfIterState iter_state =
93   {
94     .result = result,
95     .initial_kv_pair_printed = FALSE
96   };
97   gint i;
98 
99   for (i = 0; i < args->num_messages; i++)
100     {
101       value_pairs_foreach_sorted(state->vp,
102                                  tf_format_welf_foreach, (GCompareFunc) tf_format_welf_strcmp,
103                                  args->messages[i], args->options, &iter_state);
104     }
105 
106 }
107 
108 static void
tf_format_welf_free_state(gpointer s)109 tf_format_welf_free_state(gpointer s)
110 {
111   TFWelfState *state = (TFWelfState *) s;
112 
113   value_pairs_unref(state->vp);
114   tf_simple_func_free_state(s);
115 }
116 
117 TEMPLATE_FUNCTION(TFWelfState, tf_format_welf, tf_format_welf_prepare, NULL, tf_format_welf_call,
118                   tf_format_welf_free_state, NULL);
119