No issues found
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
14 *
15 *
16 * Authors:
17 * Not Zed <notzed@lostzed.mmc.com.au>
18 * Jeffrey Stedfast <fejj@ximian.com>
19 *
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <string.h>
29 #include <sys/types.h>
30 #include <regex.h>
31
32 #include <gtk/gtk.h>
33 #include <glib/gi18n.h>
34
35 #include "libevolution-utils/e-alert.h"
36
37 #include "e-filter-input.h"
38
39 G_DEFINE_TYPE (
40 EFilterInput,
41 e_filter_input,
42 E_TYPE_FILTER_ELEMENT)
43
44 static void
45 filter_input_entry_changed (GtkEntry *entry,
46 EFilterElement *element)
47 {
48 EFilterInput *input = E_FILTER_INPUT (element);
49 const gchar *text;
50
51 g_list_foreach (input->values, (GFunc) g_free, NULL);
52 g_list_free (input->values);
53
54 text = gtk_entry_get_text (entry);
55 input->values = g_list_append (NULL, g_strdup (text));
56 }
57
58 static void
59 filter_input_finalize (GObject *object)
60 {
61 EFilterInput *input = E_FILTER_INPUT (object);
62
63 xmlFree (input->type);
64
65 g_list_foreach (input->values, (GFunc) g_free, NULL);
66 g_list_free (input->values);
67
68 /* Chain up to parent's finalize() method. */
69 G_OBJECT_CLASS (e_filter_input_parent_class)->finalize (object);
70 }
71
72 static gboolean
73 filter_input_validate (EFilterElement *element,
74 EAlert **alert)
75 {
76 EFilterInput *input = E_FILTER_INPUT (element);
77 gboolean valid = TRUE;
78
79 g_warn_if_fail (alert == NULL || *alert == NULL);
80
81 if (input->values && !strcmp (input->type, "regex")) {
82 const gchar *pattern;
83 regex_t regexpat;
84 gint regerr;
85
86 pattern = input->values->data;
87
88 regerr = regcomp (
89 ®expat, pattern,
90 REG_EXTENDED | REG_NEWLINE | REG_ICASE);
91 if (regerr != 0) {
92 if (alert) {
93 gsize reglen;
94 gchar *regmsg;
95
96 /* regerror gets called twice to get the full error string
97 * length to do proper posix error reporting */
98 reglen = regerror (regerr, ®expat, 0, 0);
99 regmsg = g_malloc0 (reglen + 1);
100 regerror (regerr, ®expat, regmsg, reglen);
101
102 *alert = e_alert_new ("filter:bad-regexp",
103 pattern, regmsg, NULL);
104 g_free (regmsg);
105 }
106
107 valid = FALSE;
108 }
109
110 regfree (®expat);
111 }
112
113 return valid;
114 }
115
116 static gint
117 filter_input_eq (EFilterElement *element_a,
118 EFilterElement *element_b)
119 {
120 EFilterInput *input_a = E_FILTER_INPUT (element_a);
121 EFilterInput *input_b = E_FILTER_INPUT (element_b);
122 GList *link_a;
123 GList *link_b;
124
125 /* Chain up to parent's eq() method. */
126 if (!E_FILTER_ELEMENT_CLASS (e_filter_input_parent_class)->
127 eq (element_a, element_b))
128 return FALSE;
129
130 if (g_strcmp0 (input_a->type, input_b->type) != 0)
131 return FALSE;
132
133 link_a = input_a->values;
134 link_b = input_b->values;
135
136 while (link_a != NULL && link_b != NULL) {
137 if (g_strcmp0 (link_a->data, link_b->data) != 0)
138 return FALSE;
139
140 link_a = g_list_next (link_a);
141 link_b = g_list_next (link_b);
142 }
143
144 if (link_a != NULL || link_b != NULL)
145 return FALSE;
146
147 return TRUE;
148 }
149
150 static xmlNodePtr
151 filter_input_xml_encode (EFilterElement *element)
152 {
153 EFilterInput *input = E_FILTER_INPUT (element);
154 xmlNodePtr value;
155 GList *link;
156 const gchar *type;
157
158 type = input->type ? input->type : "string";
159
160 value = xmlNewNode (NULL, (xmlChar *) "value");
161 xmlSetProp (value, (xmlChar *) "name", (xmlChar *) element->name);
162 xmlSetProp (value, (xmlChar *) "type", (xmlChar *) type);
163
164 for (link = input->values; link != NULL; link = g_list_next (link)) {
165 xmlChar *str = link->data;
166 xmlNodePtr cur;
167
168 cur = xmlNewChild (value, NULL, (xmlChar *) type, NULL);
169
170 str = xmlEncodeEntitiesReentrant (NULL, str);
171 xmlNodeSetContent (cur, str);
172 xmlFree (str);
173 }
174
175 return value;
176 }
177
178 static gint
179 filter_input_xml_decode (EFilterElement *element,
180 xmlNodePtr node)
181 {
182 EFilterInput *input = (EFilterInput *) element;
183 gchar *name, *str, *type;
184 xmlNodePtr child;
185
186 g_list_foreach (input->values, (GFunc) g_free, NULL);
187 g_list_free (input->values);
188 input->values = NULL;
189
190 name = (gchar *) xmlGetProp (node, (xmlChar *) "name");
191 type = (gchar *) xmlGetProp (node, (xmlChar *) "type");
192
193 xmlFree (element->name);
194 element->name = name;
195
196 xmlFree (input->type);
197 input->type = type;
198
199 child = node->children;
200 while (child != NULL) {
201 if (!strcmp ((gchar *) child->name, type)) {
202 if (!(str = (gchar *) xmlNodeGetContent (child)))
203 str = (gchar *) xmlStrdup ((xmlChar *)"");
204
205 input->values = g_list_append (input->values, g_strdup (str));
206 xmlFree (str);
207 } else if (child->type == XML_ELEMENT_NODE) {
208 g_warning (
209 "Unknown node type '%s' encountered "
210 "decoding a %s\n", child->name, type);
211 }
212 child = child->next;
213 }
214
215 return 0;
216 }
217
218 static GtkWidget *
219 filter_input_get_widget (EFilterElement *element)
220 {
221 EFilterInput *input = E_FILTER_INPUT (element);
222 GtkWidget *entry;
223
224 entry = gtk_entry_new ();
225 if (input->values && input->values->data)
226 gtk_entry_set_text (
227 GTK_ENTRY (entry), input->values->data);
228
229 g_signal_connect (
230 entry, "changed",
231 G_CALLBACK (filter_input_entry_changed), element);
232
233 return entry;
234 }
235
236 static void
237 filter_input_format_sexp (EFilterElement *element,
238 GString *out)
239 {
240 EFilterInput *input = E_FILTER_INPUT (element);
241 GList *link;
242
243 for (link = input->values; link != NULL; link = g_list_next (link))
244 camel_sexp_encode_string (out, link->data);
245 }
246
247 static void
248 e_filter_input_class_init (EFilterInputClass *class)
249 {
250 GObjectClass *object_class;
251 EFilterElementClass *filter_element_class;
252
253 object_class = G_OBJECT_CLASS (class);
254 object_class->finalize = filter_input_finalize;
255
256 filter_element_class = E_FILTER_ELEMENT_CLASS (class);
257 filter_element_class->validate = filter_input_validate;
258 filter_element_class->eq = filter_input_eq;
259 filter_element_class->xml_encode = filter_input_xml_encode;
260 filter_element_class->xml_decode = filter_input_xml_decode;
261 filter_element_class->get_widget = filter_input_get_widget;
262 filter_element_class->format_sexp = filter_input_format_sexp;
263 }
264
265 static void
266 e_filter_input_init (EFilterInput *input)
267 {
268 input->values = g_list_prepend (NULL, g_strdup (""));
269 }
270
271 /**
272 * filter_input_new:
273 *
274 * Create a new EFilterInput object.
275 *
276 * Return value: A new #EFilterInput object.
277 **/
278 EFilterInput *
279 e_filter_input_new (void)
280 {
281 return g_object_new (E_TYPE_FILTER_INPUT, NULL);
282 }
283
284 EFilterInput *
285 e_filter_input_new_type_name (const gchar *type)
286 {
287 EFilterInput *input;
288
289 input = e_filter_input_new ();
290 input->type = (gchar *) xmlStrdup ((xmlChar *) type);
291
292 return input;
293 }
294
295 void
296 e_filter_input_set_value (EFilterInput *input,
297 const gchar *value)
298 {
299 g_return_if_fail (E_IS_FILTER_INPUT (input));
300
301 g_list_foreach (input->values, (GFunc) g_free, NULL);
302 g_list_free (input->values);
303
304 input->values = g_list_append (NULL, g_strdup (value));
305 }