1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimppluginmanager-file.c
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #include "config.h"
21 
22 #include <string.h>
23 
24 #include <gdk-pixbuf/gdk-pixbuf.h>
25 #include <gegl.h>
26 
27 #include "plug-in-types.h"
28 
29 #include "core/gimp.h"
30 #include "core/gimpparamspecs.h"
31 
32 #include "gimpplugin.h"
33 #include "gimpplugindef.h"
34 #include "gimppluginmanager.h"
35 #include "gimppluginmanager-file.h"
36 #include "gimppluginmanager-file-procedure.h"
37 #include "gimppluginprocedure.h"
38 
39 
40 static gboolean   file_procedure_in_group (GimpPlugInProcedure    *file_proc,
41                                            GimpFileProcedureGroup  group);
42 
43 
44 /*  public functions  */
45 
46 gboolean
gimp_plug_in_manager_register_load_handler(GimpPlugInManager * manager,const gchar * name,const gchar * extensions,const gchar * prefixes,const gchar * magics)47 gimp_plug_in_manager_register_load_handler (GimpPlugInManager *manager,
48                                             const gchar       *name,
49                                             const gchar       *extensions,
50                                             const gchar       *prefixes,
51                                             const gchar       *magics)
52 {
53   GimpPlugInProcedure *file_proc;
54   GimpProcedure       *procedure;
55   GSList              *list;
56 
57   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), FALSE);
58   g_return_val_if_fail (name != NULL, FALSE);
59 
60   if (manager->current_plug_in && manager->current_plug_in->plug_in_def)
61     list = manager->current_plug_in->plug_in_def->procedures;
62   else
63     list = manager->plug_in_procedures;
64 
65   file_proc = gimp_plug_in_procedure_find (list, name);
66 
67   if (! file_proc)
68     {
69       gimp_message (manager->gimp, NULL, GIMP_MESSAGE_ERROR,
70                     "attempt to register nonexistent load handler \"%s\"",
71                     name);
72       return FALSE;
73     }
74 
75   procedure = GIMP_PROCEDURE (file_proc);
76 
77   if ((procedure->num_args   < 3)                        ||
78       (procedure->num_values < 1)                        ||
79       ! GIMP_IS_PARAM_SPEC_INT32    (procedure->args[0]) ||
80       ! G_IS_PARAM_SPEC_STRING      (procedure->args[1]) ||
81       ! G_IS_PARAM_SPEC_STRING      (procedure->args[2]) ||
82       ! GIMP_IS_PARAM_SPEC_IMAGE_ID (procedure->values[0]))
83     {
84       gimp_message (manager->gimp, NULL, GIMP_MESSAGE_ERROR,
85                     "load handler \"%s\" does not take the standard "
86                     "load handler args", name);
87       return FALSE;
88     }
89 
90   gimp_plug_in_procedure_set_file_proc (file_proc,
91                                         extensions, prefixes, magics);
92 
93   if (! g_slist_find (manager->load_procs, file_proc))
94     manager->load_procs = g_slist_prepend (manager->load_procs, file_proc);
95 
96   return TRUE;
97 }
98 
99 gboolean
gimp_plug_in_manager_register_save_handler(GimpPlugInManager * manager,const gchar * name,const gchar * extensions,const gchar * prefixes)100 gimp_plug_in_manager_register_save_handler (GimpPlugInManager *manager,
101                                             const gchar       *name,
102                                             const gchar       *extensions,
103                                             const gchar       *prefixes)
104 {
105   GimpPlugInProcedure *file_proc;
106   GimpProcedure       *procedure;
107   GSList              *list;
108 
109   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), FALSE);
110   g_return_val_if_fail (name != NULL, FALSE);
111 
112   if (manager->current_plug_in && manager->current_plug_in->plug_in_def)
113     list = manager->current_plug_in->plug_in_def->procedures;
114   else
115     list = manager->plug_in_procedures;
116 
117   file_proc = gimp_plug_in_procedure_find (list, name);
118 
119   if (! file_proc)
120     {
121       gimp_message (manager->gimp, NULL, GIMP_MESSAGE_ERROR,
122                     "attempt to register nonexistent save handler \"%s\"",
123                     name);
124       return FALSE;
125     }
126 
127   procedure = GIMP_PROCEDURE (file_proc);
128 
129   if ((procedure->num_args < 5)                             ||
130       ! GIMP_IS_PARAM_SPEC_INT32       (procedure->args[0]) ||
131       ! GIMP_IS_PARAM_SPEC_IMAGE_ID    (procedure->args[1]) ||
132       ! GIMP_IS_PARAM_SPEC_DRAWABLE_ID (procedure->args[2]) ||
133       ! G_IS_PARAM_SPEC_STRING         (procedure->args[3]) ||
134       ! G_IS_PARAM_SPEC_STRING         (procedure->args[4]))
135     {
136       gimp_message (manager->gimp, NULL, GIMP_MESSAGE_ERROR,
137                     "save handler \"%s\" does not take the standard "
138                     "save handler args", name);
139       return FALSE;
140     }
141 
142   gimp_plug_in_procedure_set_file_proc (file_proc,
143                                         extensions, prefixes, NULL);
144 
145   if (file_procedure_in_group (file_proc, GIMP_FILE_PROCEDURE_GROUP_SAVE))
146     {
147       if (! g_slist_find (manager->save_procs, file_proc))
148         manager->save_procs = g_slist_prepend (manager->save_procs, file_proc);
149     }
150 
151   if (file_procedure_in_group (file_proc, GIMP_FILE_PROCEDURE_GROUP_EXPORT))
152     {
153       if (! g_slist_find (manager->export_procs, file_proc))
154         manager->export_procs = g_slist_prepend (manager->export_procs, file_proc);
155     }
156 
157   return TRUE;
158 }
159 
160 gboolean
gimp_plug_in_manager_register_priority(GimpPlugInManager * manager,const gchar * name,gint priority)161 gimp_plug_in_manager_register_priority (GimpPlugInManager *manager,
162                                         const gchar       *name,
163                                         gint               priority)
164 {
165   GimpPlugInProcedure *file_proc;
166   GSList              *list;
167 
168   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), FALSE);
169   g_return_val_if_fail (name != NULL, FALSE);
170 
171   if (manager->current_plug_in && manager->current_plug_in->plug_in_def)
172     list = manager->current_plug_in->plug_in_def->procedures;
173   else
174     list = manager->plug_in_procedures;
175 
176   file_proc = gimp_plug_in_procedure_find (list, name);
177 
178   if (! file_proc)
179     return FALSE;
180 
181   gimp_plug_in_procedure_set_priority (file_proc, priority);
182 
183   return TRUE;
184 }
185 
186 gboolean
gimp_plug_in_manager_register_mime_types(GimpPlugInManager * manager,const gchar * name,const gchar * mime_types)187 gimp_plug_in_manager_register_mime_types (GimpPlugInManager *manager,
188                                           const gchar       *name,
189                                           const gchar       *mime_types)
190 {
191   GimpPlugInProcedure *file_proc;
192   GSList              *list;
193 
194   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), FALSE);
195   g_return_val_if_fail (name != NULL, FALSE);
196   g_return_val_if_fail (mime_types != NULL, FALSE);
197 
198   if (manager->current_plug_in && manager->current_plug_in->plug_in_def)
199     list = manager->current_plug_in->plug_in_def->procedures;
200   else
201     list = manager->plug_in_procedures;
202 
203   file_proc = gimp_plug_in_procedure_find (list, name);
204 
205   if (! file_proc)
206     return FALSE;
207 
208   gimp_plug_in_procedure_set_mime_types (file_proc, mime_types);
209 
210   return TRUE;
211 }
212 
213 gboolean
gimp_plug_in_manager_register_handles_uri(GimpPlugInManager * manager,const gchar * name)214 gimp_plug_in_manager_register_handles_uri (GimpPlugInManager *manager,
215                                            const gchar       *name)
216 {
217   GimpPlugInProcedure *file_proc;
218   GSList              *list;
219 
220   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), FALSE);
221   g_return_val_if_fail (name != NULL, FALSE);
222 
223   if (manager->current_plug_in && manager->current_plug_in->plug_in_def)
224     list = manager->current_plug_in->plug_in_def->procedures;
225   else
226     list = manager->plug_in_procedures;
227 
228   file_proc = gimp_plug_in_procedure_find (list, name);
229 
230   if (! file_proc)
231     return FALSE;
232 
233   gimp_plug_in_procedure_set_handles_uri (file_proc);
234 
235   return TRUE;
236 }
237 
238 gboolean
gimp_plug_in_manager_register_handles_raw(GimpPlugInManager * manager,const gchar * name)239 gimp_plug_in_manager_register_handles_raw (GimpPlugInManager *manager,
240                                            const gchar       *name)
241 {
242   GimpPlugInProcedure *file_proc;
243   GSList              *list;
244 
245   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), FALSE);
246   g_return_val_if_fail (name != NULL, FALSE);
247 
248   if (manager->current_plug_in && manager->current_plug_in->plug_in_def)
249     list = manager->current_plug_in->plug_in_def->procedures;
250   else
251     list = manager->plug_in_procedures;
252 
253   file_proc = gimp_plug_in_procedure_find (list, name);
254 
255   if (! file_proc)
256     return FALSE;
257 
258   gimp_plug_in_procedure_set_handles_raw (file_proc);
259 
260   return TRUE;
261 }
262 
263 gboolean
gimp_plug_in_manager_register_thumb_loader(GimpPlugInManager * manager,const gchar * load_proc,const gchar * thumb_proc)264 gimp_plug_in_manager_register_thumb_loader (GimpPlugInManager *manager,
265                                             const gchar       *load_proc,
266                                             const gchar       *thumb_proc)
267 {
268   GimpPlugInProcedure *file_proc;
269   GSList              *list;
270 
271   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), FALSE);
272   g_return_val_if_fail (load_proc, FALSE);
273   g_return_val_if_fail (thumb_proc, FALSE);
274 
275   if (manager->current_plug_in && manager->current_plug_in->plug_in_def)
276     list = manager->current_plug_in->plug_in_def->procedures;
277   else
278     list = manager->plug_in_procedures;
279 
280   file_proc = gimp_plug_in_procedure_find (list, load_proc);
281 
282   if (! file_proc)
283     return FALSE;
284 
285   gimp_plug_in_procedure_set_thumb_loader (file_proc, thumb_proc);
286 
287   return TRUE;
288 }
289 
290 GSList *
gimp_plug_in_manager_get_file_procedures(GimpPlugInManager * manager,GimpFileProcedureGroup group)291 gimp_plug_in_manager_get_file_procedures (GimpPlugInManager      *manager,
292                                           GimpFileProcedureGroup  group)
293 {
294   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), NULL);
295 
296   switch (group)
297     {
298     case GIMP_FILE_PROCEDURE_GROUP_NONE:
299       return NULL;
300 
301     case GIMP_FILE_PROCEDURE_GROUP_OPEN:
302       return manager->display_load_procs;
303 
304     case GIMP_FILE_PROCEDURE_GROUP_SAVE:
305       return manager->display_save_procs;
306 
307     case GIMP_FILE_PROCEDURE_GROUP_EXPORT:
308       return manager->display_export_procs;
309 
310     default:
311       g_return_val_if_reached (NULL);
312     }
313 }
314 
315 GimpPlugInProcedure *
gimp_plug_in_manager_file_procedure_find(GimpPlugInManager * manager,GimpFileProcedureGroup group,GFile * file,GError ** error)316 gimp_plug_in_manager_file_procedure_find (GimpPlugInManager      *manager,
317                                           GimpFileProcedureGroup  group,
318                                           GFile                  *file,
319                                           GError                **error)
320 {
321   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), NULL);
322   g_return_val_if_fail (G_IS_FILE (file), NULL);
323   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
324 
325   switch (group)
326     {
327     case GIMP_FILE_PROCEDURE_GROUP_OPEN:
328       return file_procedure_find (manager->load_procs, file, error);
329 
330     case GIMP_FILE_PROCEDURE_GROUP_SAVE:
331       return file_procedure_find (manager->save_procs, file, error);
332 
333     case GIMP_FILE_PROCEDURE_GROUP_EXPORT:
334       return file_procedure_find (manager->export_procs, file, error);
335 
336     default:
337       g_return_val_if_reached (NULL);
338     }
339 }
340 
341 GimpPlugInProcedure *
gimp_plug_in_manager_file_procedure_find_by_prefix(GimpPlugInManager * manager,GimpFileProcedureGroup group,GFile * file)342 gimp_plug_in_manager_file_procedure_find_by_prefix (GimpPlugInManager      *manager,
343                                                     GimpFileProcedureGroup  group,
344                                                     GFile                  *file)
345 {
346   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), NULL);
347   g_return_val_if_fail (G_IS_FILE (file), NULL);
348 
349   switch (group)
350     {
351     case GIMP_FILE_PROCEDURE_GROUP_OPEN:
352       return file_procedure_find_by_prefix (manager->load_procs, file);
353 
354     case GIMP_FILE_PROCEDURE_GROUP_SAVE:
355       return file_procedure_find_by_prefix (manager->save_procs, file);
356 
357     case GIMP_FILE_PROCEDURE_GROUP_EXPORT:
358       return file_procedure_find_by_prefix (manager->export_procs, file);
359 
360     default:
361       g_return_val_if_reached (NULL);
362     }
363 }
364 
365 GimpPlugInProcedure *
gimp_plug_in_manager_file_procedure_find_by_extension(GimpPlugInManager * manager,GimpFileProcedureGroup group,GFile * file)366 gimp_plug_in_manager_file_procedure_find_by_extension (GimpPlugInManager      *manager,
367                                                        GimpFileProcedureGroup  group,
368                                                        GFile                  *file)
369 {
370   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), NULL);
371   g_return_val_if_fail (G_IS_FILE (file), NULL);
372 
373   switch (group)
374     {
375     case GIMP_FILE_PROCEDURE_GROUP_OPEN:
376       return file_procedure_find_by_extension (manager->load_procs, file);
377 
378     case GIMP_FILE_PROCEDURE_GROUP_SAVE:
379       return file_procedure_find_by_extension (manager->save_procs, file);
380 
381     case GIMP_FILE_PROCEDURE_GROUP_EXPORT:
382       return file_procedure_find_by_extension (manager->export_procs, file);
383 
384     default:
385       g_return_val_if_reached (NULL);
386     }
387 }
388 
389 GimpPlugInProcedure *
gimp_plug_in_manager_file_procedure_find_by_mime_type(GimpPlugInManager * manager,GimpFileProcedureGroup group,const gchar * mime_type)390 gimp_plug_in_manager_file_procedure_find_by_mime_type (GimpPlugInManager      *manager,
391                                                        GimpFileProcedureGroup  group,
392                                                        const gchar            *mime_type)
393 {
394   g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), NULL);
395   g_return_val_if_fail (mime_type != NULL, NULL);
396 
397   switch (group)
398     {
399     case GIMP_FILE_PROCEDURE_GROUP_OPEN:
400       return file_procedure_find_by_mime_type (manager->load_procs, mime_type);
401 
402     case GIMP_FILE_PROCEDURE_GROUP_SAVE:
403       return file_procedure_find_by_mime_type (manager->save_procs, mime_type);
404 
405     case GIMP_FILE_PROCEDURE_GROUP_EXPORT:
406       return file_procedure_find_by_mime_type (manager->export_procs, mime_type);
407 
408     default:
409       g_return_val_if_reached (NULL);
410     }
411 }
412 
413 
414 /*  private functions  */
415 
416 static gboolean
file_procedure_in_group(GimpPlugInProcedure * file_proc,GimpFileProcedureGroup group)417 file_procedure_in_group (GimpPlugInProcedure    *file_proc,
418                          GimpFileProcedureGroup  group)
419 {
420   const gchar *name        = gimp_object_get_name (file_proc);
421   gboolean     is_xcf_save = FALSE;
422   gboolean     is_filter   = FALSE;
423 
424   is_xcf_save = (strcmp (name, "gimp-xcf-save") == 0);
425 
426   is_filter   = (strcmp (name, "file-gz-save")  == 0 ||
427                  strcmp (name, "file-bz2-save") == 0 ||
428                  strcmp (name, "file-xz-save")  == 0);
429 
430   switch (group)
431     {
432     case GIMP_FILE_PROCEDURE_GROUP_NONE:
433       return FALSE;
434 
435     case GIMP_FILE_PROCEDURE_GROUP_SAVE:
436       /* Only .xcf shall pass */
437       return is_xcf_save || is_filter;
438 
439     case GIMP_FILE_PROCEDURE_GROUP_EXPORT:
440       /* Anything but .xcf shall pass */
441       return ! is_xcf_save;
442 
443     case GIMP_FILE_PROCEDURE_GROUP_OPEN:
444       /* No filter applied for Open */
445       return TRUE;
446 
447     default:
448     case GIMP_FILE_PROCEDURE_GROUP_ANY:
449       return TRUE;
450     }
451 }
452