evolution-3.6.4/filter/e-filter-input.c

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 			&regexpat, 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, &regexpat, 0, 0);
 99 				regmsg = g_malloc0 (reglen + 1);
100 				regerror (regerr, &regexpat, 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 (&regexpat);
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 }