1 /*
2 * caja-extension.c - extension management functions
3 *
4 * Copyright (C) 2012-2021 The MATE developers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 * Author: Alexander van der Meij <alexandervdm@gliese.me>
22 */
23
24 #include "caja-extensions.h"
25
26 #include "caja-global-preferences.h"
27 #include "caja-module.h"
28 #include "caja-debug-log.h"
29
30 #include <string.h>
31
32 #define CAJA_EXTENSION_GROUP "Caja Extension"
33
34 static GList *caja_extensions = NULL;
35
36
37 static Extension *
extension_new(gchar * filename,gboolean state,gboolean python,GObject * module)38 extension_new (gchar *filename, gboolean state, gboolean python, GObject *module)
39 {
40 GError *error = NULL;
41 Extension *ext;
42 GKeyFile *extension_file;
43 gchar *extension_filename;
44
45 ext = g_new0 (Extension, 1);
46 ext->filename = filename;
47 ext->name = NULL;
48 ext->description = NULL;
49 ext->author = NULL;
50 ext->copyright = NULL;
51 ext->version = NULL;
52 ext->website = NULL;
53 ext->state = state;
54 ext->module = module;
55
56 extension_file = g_key_file_new ();
57 extension_filename = g_strdup_printf(CAJA_DATADIR "/extensions/%s.caja-extension", filename);
58 if (g_key_file_load_from_file (extension_file, extension_filename, G_KEY_FILE_NONE, &error))
59 {
60 ext->name = g_key_file_get_locale_string (extension_file, CAJA_EXTENSION_GROUP, "Name", NULL, NULL);
61 ext->description = g_key_file_get_locale_string (extension_file, CAJA_EXTENSION_GROUP, "Description", NULL, NULL);
62 ext->icon = g_key_file_get_string (extension_file, CAJA_EXTENSION_GROUP, "Icon", NULL);
63 ext->author = g_key_file_get_string_list (extension_file, CAJA_EXTENSION_GROUP, "Author", NULL, NULL);
64 ext->copyright = g_key_file_get_locale_string (extension_file, CAJA_EXTENSION_GROUP, "Copyright", NULL, NULL);
65 ext->version = g_key_file_get_string (extension_file, CAJA_EXTENSION_GROUP, "Version", NULL);
66 ext->website = g_key_file_get_string (extension_file, CAJA_EXTENSION_GROUP, "Website", NULL);
67 g_key_file_free (extension_file);
68 }
69 else
70 {
71 caja_debug_log (FALSE, CAJA_DEBUG_LOG_DOMAIN_USER, "Error loading keys from file: %s\n", error->message);
72 g_error_free (error);
73 }
74 g_free (extension_filename);
75
76 if (python)
77 {
78 ext->name = g_strconcat("Python: ", filename, NULL);
79 ext->description = "Python-caja extension";
80 }
81
82 return ext;
83 }
84
85 /* functions related to persistent configuration through gsettings: */
86
87 static gboolean
gsettings_key_has_value(const gchar * value)88 gsettings_key_has_value (const gchar *value)
89 {
90 gchar **list;
91 gint i;
92
93 list = g_settings_get_strv (caja_extension_preferences,
94 CAJA_PREFERENCES_DISABLED_EXTENSIONS);
95
96 if (list != NULL)
97 {
98 for (i = 0; list[i]; i++)
99 {
100 if (g_ascii_strcasecmp (value, list[i]) == 0)
101 {
102 g_strfreev (list);
103 return TRUE;
104 }
105 }
106 }
107 g_strfreev (list);
108 return FALSE;
109 }
110
111 static gboolean
gsettings_append_to_list(const char * value)112 gsettings_append_to_list (const char *value)
113 {
114 gchar **current;
115 gchar **new;
116 gint size;
117 gboolean retval;
118
119 current = g_settings_get_strv (caja_extension_preferences,
120 CAJA_PREFERENCES_DISABLED_EXTENSIONS);
121
122 for (size = 0; current[size] != NULL; size++);
123
124 size += 1;
125 size += 1;
126
127 new = g_realloc_n (current, size, sizeof (gchar *));
128
129 new[size - 2] = g_strdup (value);
130 new[size - 1] = NULL;
131
132 retval = g_settings_set_strv (caja_extension_preferences,
133 CAJA_PREFERENCES_DISABLED_EXTENSIONS,
134 (const gchar **) new);
135
136 g_strfreev (new);
137 return retval;
138 }
139
140 static gboolean
gsettings_remove_from_list(const char * value)141 gsettings_remove_from_list (const char *value)
142 {
143 gchar **current;
144 GArray *array;
145 gint i;
146 gboolean retval;
147
148 current = g_settings_get_strv (caja_extension_preferences,
149 CAJA_PREFERENCES_DISABLED_EXTENSIONS);
150
151 array = g_array_new (TRUE, TRUE, sizeof (gchar *));
152
153 for (i = 0; current[i] != NULL; i++)
154 {
155 if (g_strcmp0 (current[i], value) != 0)
156 array = g_array_append_val (array, current[i]);
157 }
158
159 retval = g_settings_set_strv (caja_extension_preferences,
160 CAJA_PREFERENCES_DISABLED_EXTENSIONS,
161 (const gchar **) array->data);
162
163 g_strfreev (current);
164 g_array_free (array, TRUE);
165 return retval;
166 }
167
168 /* functions related to the extension management */
169
170 static gboolean
caja_extension_get_state(const gchar * extname)171 caja_extension_get_state (const gchar *extname)
172 {
173 return !gsettings_key_has_value (extname);
174 }
175
176 GList *
caja_extensions_get_for_type(GType type)177 caja_extensions_get_for_type (GType type)
178 {
179 GList *l;
180 GList *ret = NULL;
181
182 for (l = caja_extensions; l != NULL; l = l->next)
183 {
184 Extension *ext = l->data;
185 ext->state = caja_extension_get_state (ext->filename);
186 if (ext->state) // only load enabled extensions
187 {
188 if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (ext->module), type))
189 {
190 g_object_ref (ext->module);
191 ret = g_list_prepend (ret, ext->module);
192 }
193 }
194 }
195
196 return ret;
197 }
198
199 GList *
caja_extensions_get_list(void)200 caja_extensions_get_list (void)
201 {
202 return caja_extensions;
203 }
204
205 void
caja_extension_register(gchar * filename,GObject * module)206 caja_extension_register (gchar *filename, GObject *module)
207 {
208 gboolean ext_state = TRUE; // new extensions are enabled by default.
209 gboolean ext_python = FALSE;
210 gchar *ext_filename;
211
212 ext_filename = g_strndup (filename, strlen(filename) - 3);
213 ext_state = caja_extension_get_state (ext_filename);
214
215 if (g_str_has_suffix (filename, ".py")) {
216 ext_python = TRUE;
217 }
218
219 Extension *ext = extension_new (ext_filename, ext_state, ext_python, module);
220 caja_extensions = g_list_append (caja_extensions, ext);
221 }
222
223 gboolean
caja_extension_set_state(Extension * ext,gboolean new_state)224 caja_extension_set_state (Extension *ext, gboolean new_state)
225 {
226 if (ext)
227 {
228 g_return_val_if_fail (ext->state != new_state, FALSE);
229 ext->state = new_state;
230 }
231
232 gboolean retval;
233 if (new_state) {
234 retval = gsettings_remove_from_list (ext->filename);
235 }
236 else {
237 retval = gsettings_append_to_list (ext->filename);
238 }
239
240 g_return_val_if_fail (retval == TRUE, FALSE);
241 return TRUE;
242 }
243
244