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 * Jeffrey Stedfast <fejj@ximian.com>
18 *
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20 *
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <string.h>
28 #include <sys/types.h>
29
30 #include <gtk/gtk.h>
31 #include <glib/gi18n.h>
32 #include <glib/gstdio.h>
33
34 #include "libevolution-utils/e-alert.h"
35
36 #include "e-filter-file.h"
37 #include "e-filter-part.h"
38
39 G_DEFINE_TYPE (
40 EFilterFile,
41 e_filter_file,
42 E_TYPE_FILTER_ELEMENT)
43
44 static void
45 filter_file_filename_changed (GtkFileChooser *file_chooser,
46 EFilterElement *element)
47 {
48 EFilterFile *file = E_FILTER_FILE (element);
49 const gchar *path;
50
51 path = gtk_file_chooser_get_filename (file_chooser);
52
53 g_free (file->path);
54 file->path = g_strdup (path);
55 }
56
57 static void
58 filter_file_finalize (GObject *object)
59 {
60 EFilterFile *file = E_FILTER_FILE (object);
61
62 xmlFree (file->type);
63 g_free (file->path);
64
65 /* Chain up to parent's finalize() method. */
66 G_OBJECT_CLASS (e_filter_file_parent_class)->finalize (object);
67 }
68
69 static gboolean
70 filter_file_validate (EFilterElement *element,
71 EAlert **alert)
72 {
73 EFilterFile *file = E_FILTER_FILE (element);
74
75 g_warn_if_fail (alert == NULL || *alert == NULL);
76
77 if (!file->path) {
78 if (alert)
79 *alert = e_alert_new ("filter:no-file", NULL);
80 return FALSE;
81 }
82
83 /* FIXME: do more to validate command-lines? */
84
85 if (g_strcmp0 (file->type, "file") == 0) {
86 if (!g_file_test (file->path, G_FILE_TEST_IS_REGULAR)) {
87 if (alert)
88 *alert = e_alert_new ("filter:bad-file",
89 file->path, NULL);
90 return FALSE;
91 }
92 } else if (g_strcmp0 (file->type, "command") == 0) {
93 /* Only requirements so far is that the
94 * command can't be an empty string. */
95 return (file->path[0] != '\0');
96 }
97
98 return TRUE;
99 }
100
101 static gint
102 filter_file_eq (EFilterElement *element_a,
103 EFilterElement *element_b)
104 {
105 EFilterFile *file_a = E_FILTER_FILE (element_a);
106 EFilterFile *file_b = E_FILTER_FILE (element_b);
107
108 /* Chain up to parent's eq() method. */
109 if (!E_FILTER_ELEMENT_CLASS (e_filter_file_parent_class)->
110 eq (element_a, element_b))
111 return FALSE;
112
113 if (g_strcmp0 (file_a->path, file_b->path) != 0)
114 return FALSE;
115
116 if (g_strcmp0 (file_a->type, file_b->type) != 0)
117 return FALSE;
118
119 return TRUE;
120 }
121
122 static xmlNodePtr
123 filter_file_xml_encode (EFilterElement *element)
124 {
125 EFilterFile *file = E_FILTER_FILE (element);
126 xmlNodePtr cur, value;
127 const gchar *type;
128
129 type = file->type ? file->type : "file";
130
131 value = xmlNewNode (NULL, (xmlChar *)"value");
132 xmlSetProp (value, (xmlChar *) "name", (xmlChar *) element->name);
133 xmlSetProp (value, (xmlChar *) "type", (xmlChar *) type);
134
135 cur = xmlNewChild (value, NULL, (xmlChar *) type, NULL);
136 xmlNodeSetContent (cur, (xmlChar *) file->path);
137
138 return value;
139 }
140
141 static gint
142 filter_file_xml_decode (EFilterElement *element,
143 xmlNodePtr node)
144 {
145 EFilterFile *file = E_FILTER_FILE (element);
146 gchar *name, *str, *type;
147 xmlNodePtr child;
148
149 name = (gchar *) xmlGetProp (node, (xmlChar *) "name");
150 type = (gchar *) xmlGetProp (node, (xmlChar *) "type");
151
152 xmlFree (element->name);
153 element->name = name;
154
155 xmlFree (file->type);
156 file->type = type;
157
158 g_free (file->path);
159 file->path = NULL;
160
161 child = node->children;
162 while (child != NULL) {
163 if (!strcmp ((gchar *) child->name, type)) {
164 str = (gchar *) xmlNodeGetContent (child);
165 file->path = g_strdup (str ? str : "");
166 xmlFree (str);
167
168 break;
169 } else if (child->type == XML_ELEMENT_NODE) {
170 g_warning (
171 "Unknown node type '%s' encountered "
172 "decoding a %s\n", child->name, type);
173 }
174
175 child = child->next;
176 }
177
178 return 0;
179 }
180
181 static GtkWidget *
182 filter_file_get_widget (EFilterElement *element)
183 {
184 EFilterFile *file = E_FILTER_FILE (element);
185 GtkWidget *widget;
186
187 widget = gtk_file_chooser_button_new (
188 _("Choose a File"), GTK_FILE_CHOOSER_ACTION_OPEN);
189 gtk_file_chooser_set_filename (
190 GTK_FILE_CHOOSER (widget), file->path);
191 g_signal_connect (
192 widget, "selection-changed",
193 G_CALLBACK (filter_file_filename_changed), element);
194
195 return widget;
196 }
197
198 static void
199 filter_file_format_sexp (EFilterElement *element,
200 GString *out)
201 {
202 EFilterFile *file = E_FILTER_FILE (element);
203
204 camel_sexp_encode_string (out, file->path);
205 }
206
207 static void
208 e_filter_file_class_init (EFilterFileClass *class)
209 {
210 GObjectClass *object_class;
211 EFilterElementClass *filter_element_class;
212
213 object_class = G_OBJECT_CLASS (class);
214 object_class->finalize = filter_file_finalize;
215
216 filter_element_class = E_FILTER_ELEMENT_CLASS (class);
217 filter_element_class->validate = filter_file_validate;
218 filter_element_class->eq = filter_file_eq;
219 filter_element_class->xml_encode = filter_file_xml_encode;
220 filter_element_class->xml_decode = filter_file_xml_decode;
221 filter_element_class->get_widget = filter_file_get_widget;
222 filter_element_class->format_sexp = filter_file_format_sexp;
223 }
224
225 static void
226 e_filter_file_init (EFilterFile *filter)
227 {
228 }
229
230 /**
231 * filter_file_new:
232 *
233 * Create a new EFilterFile object.
234 *
235 * Return value: A new #EFilterFile object.
236 **/
237 EFilterFile *
238 e_filter_file_new (void)
239 {
240 return g_object_new (E_TYPE_FILTER_FILE, NULL);
241 }
242
243 EFilterFile *
244 e_filter_file_new_type_name (const gchar *type)
245 {
246 EFilterFile *file;
247
248 file = e_filter_file_new ();
249 file->type = (gchar *) xmlStrdup ((xmlChar *) type);
250
251 return file;
252 }
253
254 void
255 e_filter_file_set_path (EFilterFile *file,
256 const gchar *path)
257 {
258 g_return_if_fail (E_IS_FILTER_FILE (file));
259
260 g_free (file->path);
261 file->path = g_strdup (path);
262 }