1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * plug-in-rc.c
5  * Copyright (C) 2001  Sven Neumann <sven@gimp.org>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include <gdk-pixbuf/gdk-pixbuf.h>
24 #include <gegl.h>
25 
26 #include "libgimpbase/gimpbase.h"
27 #include "libgimpbase/gimpprotocol.h"
28 #include "libgimpconfig/gimpconfig.h"
29 
30 #include "plug-in-types.h"
31 
32 #include "core/gimp.h"
33 
34 #include "pdb/gimp-pdb-compat.h"
35 
36 #include "gimpplugindef.h"
37 #include "gimppluginprocedure.h"
38 #include "plug-in-rc.h"
39 
40 #include "gimp-intl.h"
41 
42 
43 #define PLUG_IN_RC_FILE_VERSION 5
44 
45 
46 /*
47  *  All deserialize functions return G_TOKEN_LEFT_PAREN on success,
48  *  or the GTokenType they would have expected but didn't get,
49  *  or G_TOKEN_ERROR if the function already set an error itself.
50  */
51 
52 static GTokenType plug_in_def_deserialize        (Gimp                 *gimp,
53                                                   GScanner             *scanner,
54                                                   GSList              **plug_in_defs);
55 static GTokenType plug_in_procedure_deserialize  (GScanner             *scanner,
56                                                   Gimp                 *gimp,
57                                                   GFile                *file,
58                                                   GimpPlugInProcedure **proc);
59 static GTokenType plug_in_menu_path_deserialize  (GScanner             *scanner,
60                                                   GimpPlugInProcedure  *proc);
61 static GTokenType plug_in_icon_deserialize       (GScanner             *scanner,
62                                                   GimpPlugInProcedure  *proc);
63 static GTokenType plug_in_file_proc_deserialize  (GScanner             *scanner,
64                                                   GimpPlugInProcedure  *proc);
65 static GTokenType plug_in_proc_arg_deserialize   (GScanner             *scanner,
66                                                   Gimp                 *gimp,
67                                                   GimpProcedure        *procedure,
68                                                   gboolean              return_value);
69 static GTokenType plug_in_locale_def_deserialize (GScanner             *scanner,
70                                                   GimpPlugInDef        *plug_in_def);
71 static GTokenType plug_in_help_def_deserialize   (GScanner             *scanner,
72                                                   GimpPlugInDef        *plug_in_def);
73 static GTokenType plug_in_has_init_deserialize   (GScanner             *scanner,
74                                                   GimpPlugInDef        *plug_in_def);
75 
76 
77 enum
78 {
79   PROTOCOL_VERSION = 1,
80   FILE_VERSION,
81   PLUG_IN_DEF,
82   PROC_DEF,
83   LOCALE_DEF,
84   HELP_DEF,
85   HAS_INIT,
86   PROC_ARG,
87   MENU_PATH,
88   ICON,
89   LOAD_PROC,
90   SAVE_PROC,
91   EXTENSIONS,
92   PREFIXES,
93   MAGICS,
94   PRIORITY,
95   MIME_TYPES,
96   HANDLES_URI,
97   HANDLES_RAW,
98   THUMB_LOADER
99 };
100 
101 
102 GSList *
plug_in_rc_parse(Gimp * gimp,GFile * file,GError ** error)103 plug_in_rc_parse (Gimp    *gimp,
104                   GFile   *file,
105                   GError **error)
106 {
107   GScanner   *scanner;
108   GEnumClass *enum_class;
109   GSList     *plug_in_defs     = NULL;
110   gint        protocol_version = GIMP_PROTOCOL_VERSION;
111   gint        file_version     = PLUG_IN_RC_FILE_VERSION;
112   GTokenType  token;
113 
114   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
115   g_return_val_if_fail (G_IS_FILE (file), NULL);
116   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
117 
118   scanner = gimp_scanner_new_gfile (file, error);
119 
120   if (! scanner)
121     return NULL;
122 
123   enum_class = g_type_class_ref (GIMP_TYPE_ICON_TYPE);
124 
125   g_scanner_scope_add_symbol (scanner, 0,
126                               "protocol-version",
127                               GINT_TO_POINTER (PROTOCOL_VERSION));
128   g_scanner_scope_add_symbol (scanner, 0,
129                               "file-version",
130                               GINT_TO_POINTER (FILE_VERSION));
131   g_scanner_scope_add_symbol (scanner, 0,
132                               "plug-in-def", GINT_TO_POINTER (PLUG_IN_DEF));
133 
134   g_scanner_scope_add_symbol (scanner, PLUG_IN_DEF,
135                               "proc-def", GINT_TO_POINTER (PROC_DEF));
136   g_scanner_scope_add_symbol (scanner, PLUG_IN_DEF,
137                               "locale-def", GINT_TO_POINTER (LOCALE_DEF));
138   g_scanner_scope_add_symbol (scanner, PLUG_IN_DEF,
139                               "help-def", GINT_TO_POINTER (HELP_DEF));
140   g_scanner_scope_add_symbol (scanner, PLUG_IN_DEF,
141                               "has-init", GINT_TO_POINTER (HAS_INIT));
142   g_scanner_scope_add_symbol (scanner, PLUG_IN_DEF,
143                               "proc-arg", GINT_TO_POINTER (PROC_ARG));
144   g_scanner_scope_add_symbol (scanner, PLUG_IN_DEF,
145                               "menu-path", GINT_TO_POINTER (MENU_PATH));
146   g_scanner_scope_add_symbol (scanner, PLUG_IN_DEF,
147                               "icon", GINT_TO_POINTER (ICON));
148   g_scanner_scope_add_symbol (scanner, PLUG_IN_DEF,
149                               "load-proc", GINT_TO_POINTER (LOAD_PROC));
150   g_scanner_scope_add_symbol (scanner, PLUG_IN_DEF,
151                               "save-proc", GINT_TO_POINTER (SAVE_PROC));
152 
153   g_scanner_scope_add_symbol (scanner, LOAD_PROC,
154                               "extensions", GINT_TO_POINTER (EXTENSIONS));
155   g_scanner_scope_add_symbol (scanner, LOAD_PROC,
156                               "prefixes", GINT_TO_POINTER (PREFIXES));
157   g_scanner_scope_add_symbol (scanner, LOAD_PROC,
158                               "magics", GINT_TO_POINTER (MAGICS));
159   g_scanner_scope_add_symbol (scanner, LOAD_PROC,
160                               "priority", GINT_TO_POINTER (PRIORITY));
161   g_scanner_scope_add_symbol (scanner, LOAD_PROC,
162                               "mime-types", GINT_TO_POINTER (MIME_TYPES));
163   g_scanner_scope_add_symbol (scanner, LOAD_PROC,
164                               "handles-uri", GINT_TO_POINTER (HANDLES_URI));
165   g_scanner_scope_add_symbol (scanner, LOAD_PROC,
166                               "handles-raw", GINT_TO_POINTER (HANDLES_RAW));
167   g_scanner_scope_add_symbol (scanner, LOAD_PROC,
168                               "thumb-loader", GINT_TO_POINTER (THUMB_LOADER));
169 
170   g_scanner_scope_add_symbol (scanner, SAVE_PROC,
171                               "extensions", GINT_TO_POINTER (EXTENSIONS));
172   g_scanner_scope_add_symbol (scanner, SAVE_PROC,
173                               "prefixes", GINT_TO_POINTER (PREFIXES));
174   g_scanner_scope_add_symbol (scanner, SAVE_PROC,
175                               "priority", GINT_TO_POINTER (PRIORITY));
176   g_scanner_scope_add_symbol (scanner, SAVE_PROC,
177                               "mime-types", GINT_TO_POINTER (MIME_TYPES));
178   g_scanner_scope_add_symbol (scanner, SAVE_PROC,
179                               "handles-uri", GINT_TO_POINTER (HANDLES_URI));
180 
181   token = G_TOKEN_LEFT_PAREN;
182 
183   while (protocol_version == GIMP_PROTOCOL_VERSION   &&
184          file_version     == PLUG_IN_RC_FILE_VERSION &&
185          g_scanner_peek_next_token (scanner) == token)
186     {
187       token = g_scanner_get_next_token (scanner);
188 
189       switch (token)
190         {
191         case G_TOKEN_LEFT_PAREN:
192           token = G_TOKEN_SYMBOL;
193           break;
194 
195         case G_TOKEN_SYMBOL:
196           switch (GPOINTER_TO_INT (scanner->value.v_symbol))
197             {
198             case PROTOCOL_VERSION:
199               token = G_TOKEN_INT;
200               if (gimp_scanner_parse_int (scanner, &protocol_version))
201                 token = G_TOKEN_RIGHT_PAREN;
202               break;
203 
204             case FILE_VERSION:
205               token = G_TOKEN_INT;
206               if (gimp_scanner_parse_int (scanner, &file_version))
207                 token = G_TOKEN_RIGHT_PAREN;
208               break;
209 
210             case PLUG_IN_DEF:
211               g_scanner_set_scope (scanner, PLUG_IN_DEF);
212               token = plug_in_def_deserialize (gimp, scanner, &plug_in_defs);
213               g_scanner_set_scope (scanner, 0);
214               break;
215             default:
216               break;
217             }
218               break;
219 
220         case G_TOKEN_RIGHT_PAREN:
221           token = G_TOKEN_LEFT_PAREN;
222           break;
223 
224         default: /* do nothing */
225           break;
226         }
227     }
228 
229   if (protocol_version != GIMP_PROTOCOL_VERSION   ||
230       file_version     != PLUG_IN_RC_FILE_VERSION ||
231       token            != G_TOKEN_LEFT_PAREN)
232     {
233       if (protocol_version != GIMP_PROTOCOL_VERSION)
234         {
235           g_set_error (error,
236                        GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_VERSION,
237                        _("Skipping '%s': wrong GIMP protocol version."),
238                        gimp_file_get_utf8_name (file));
239         }
240       else if (file_version != PLUG_IN_RC_FILE_VERSION)
241         {
242           g_set_error (error,
243                        GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_VERSION,
244                        _("Skipping '%s': wrong pluginrc file format version."),
245                        gimp_file_get_utf8_name (file));
246         }
247       else if (token != G_TOKEN_ERROR)
248         {
249           g_scanner_get_next_token (scanner);
250           g_scanner_unexp_token (scanner, token, NULL, NULL, NULL,
251                                  _("fatal parse error"), TRUE);
252         }
253 
254       g_slist_free_full (plug_in_defs, (GDestroyNotify) g_object_unref);
255       plug_in_defs = NULL;
256     }
257 
258   g_type_class_unref (enum_class);
259 
260   gimp_scanner_destroy (scanner);
261 
262   return g_slist_reverse (plug_in_defs);
263 }
264 
265 static GTokenType
plug_in_def_deserialize(Gimp * gimp,GScanner * scanner,GSList ** plug_in_defs)266 plug_in_def_deserialize (Gimp      *gimp,
267                          GScanner  *scanner,
268                          GSList   **plug_in_defs)
269 {
270   GimpPlugInDef       *plug_in_def;
271   GimpPlugInProcedure *proc = NULL;
272   gchar               *path;
273   GFile               *file;
274   gint64               mtime;
275   GTokenType           token;
276   GError              *error = NULL;
277 
278   if (! gimp_scanner_parse_string (scanner, &path))
279     return G_TOKEN_STRING;
280 
281   if (! (path && *path))
282     {
283       g_scanner_error (scanner, "plug-in filename is empty");
284       return G_TOKEN_ERROR;
285     }
286 
287   file = gimp_file_new_for_config_path (path, &error);
288   g_free (path);
289 
290   if (! file)
291     {
292       g_scanner_error (scanner,
293                        "unable to parse plug-in filename: %s",
294                        error->message);
295       g_clear_error (&error);
296       return G_TOKEN_ERROR;
297     }
298 
299   plug_in_def = gimp_plug_in_def_new (file);
300   g_object_unref (file);
301 
302   if (! gimp_scanner_parse_int64 (scanner, &mtime))
303     {
304       g_object_unref (plug_in_def);
305       return G_TOKEN_INT;
306     }
307 
308   plug_in_def->mtime = mtime;
309 
310   token = G_TOKEN_LEFT_PAREN;
311 
312   while (g_scanner_peek_next_token (scanner) == token)
313     {
314       token = g_scanner_get_next_token (scanner);
315 
316       switch (token)
317         {
318         case G_TOKEN_LEFT_PAREN:
319           token = G_TOKEN_SYMBOL;
320           break;
321 
322         case G_TOKEN_SYMBOL:
323           switch (GPOINTER_TO_INT (scanner->value.v_symbol))
324             {
325             case PROC_DEF:
326               token = plug_in_procedure_deserialize (scanner, gimp,
327                                                      plug_in_def->file,
328                                                      &proc);
329 
330               if (token == G_TOKEN_LEFT_PAREN)
331                 gimp_plug_in_def_add_procedure (plug_in_def, proc);
332 
333               if (proc)
334                 g_object_unref (proc);
335               break;
336 
337             case LOCALE_DEF:
338               token = plug_in_locale_def_deserialize (scanner, plug_in_def);
339               break;
340 
341             case HELP_DEF:
342               token = plug_in_help_def_deserialize (scanner, plug_in_def);
343               break;
344 
345             case HAS_INIT:
346               token = plug_in_has_init_deserialize (scanner, plug_in_def);
347               break;
348 
349             default:
350               break;
351             }
352           break;
353 
354         case G_TOKEN_RIGHT_PAREN:
355           token = G_TOKEN_LEFT_PAREN;
356           break;
357 
358         default:
359           break;
360         }
361     }
362 
363   if (token == G_TOKEN_LEFT_PAREN)
364     {
365       token = G_TOKEN_RIGHT_PAREN;
366 
367       if (gimp_scanner_parse_token (scanner, token))
368         {
369           *plug_in_defs = g_slist_prepend (*plug_in_defs, plug_in_def);
370           return G_TOKEN_LEFT_PAREN;
371         }
372     }
373 
374   g_object_unref (plug_in_def);
375 
376   return token;
377 }
378 
379 static GTokenType
plug_in_procedure_deserialize(GScanner * scanner,Gimp * gimp,GFile * file,GimpPlugInProcedure ** proc)380 plug_in_procedure_deserialize (GScanner             *scanner,
381                                Gimp                 *gimp,
382                                GFile                *file,
383                                GimpPlugInProcedure **proc)
384 {
385   GimpProcedure   *procedure;
386   GTokenType       token;
387   gchar           *str;
388   gint             proc_type;
389   gint             n_args;
390   gint             n_return_vals;
391   gint             n_menu_paths;
392   gint             i;
393 
394   if (! gimp_scanner_parse_string (scanner, &str))
395     return G_TOKEN_STRING;
396 
397   if (! (str && *str))
398     {
399       g_scanner_error (scanner, "procedure name is empty");
400       return G_TOKEN_ERROR;
401     }
402 
403   if (! gimp_scanner_parse_int (scanner, &proc_type))
404     {
405       g_free (str);
406       return G_TOKEN_INT;
407     }
408 
409   if (proc_type != GIMP_PLUGIN &&
410       proc_type != GIMP_EXTENSION)
411     {
412       g_free (str);
413       g_scanner_error (scanner, "procedure type %d is out of range",
414                        proc_type);
415       return G_TOKEN_ERROR;
416     }
417 
418   procedure = gimp_plug_in_procedure_new (proc_type, file);
419 
420   *proc = GIMP_PLUG_IN_PROCEDURE (procedure);
421 
422   gimp_object_take_name (GIMP_OBJECT (procedure),
423                          gimp_canonicalize_identifier (str));
424 
425   procedure->original_name = str;
426 
427   if (! gimp_scanner_parse_string (scanner, &procedure->blurb))
428     return G_TOKEN_STRING;
429   if (! gimp_scanner_parse_string (scanner, &procedure->help))
430     return G_TOKEN_STRING;
431   if (! gimp_scanner_parse_string (scanner, &procedure->author))
432     return G_TOKEN_STRING;
433   if (! gimp_scanner_parse_string (scanner, &procedure->copyright))
434     return G_TOKEN_STRING;
435   if (! gimp_scanner_parse_string (scanner, &procedure->date))
436     return G_TOKEN_STRING;
437   if (! gimp_scanner_parse_string (scanner, &(*proc)->menu_label))
438     return G_TOKEN_STRING;
439 
440   if (! gimp_scanner_parse_int (scanner, &n_menu_paths))
441     return G_TOKEN_INT;
442 
443   for (i = 0; i < n_menu_paths; i++)
444     {
445       token = plug_in_menu_path_deserialize (scanner, *proc);
446       if (token != G_TOKEN_LEFT_PAREN)
447         return token;
448     }
449 
450   token = plug_in_icon_deserialize (scanner, *proc);
451   if (token != G_TOKEN_LEFT_PAREN)
452     return token;
453 
454   token = plug_in_file_proc_deserialize (scanner, *proc);
455   if (token != G_TOKEN_LEFT_PAREN)
456     return token;
457 
458   if (! gimp_scanner_parse_string (scanner, &str))
459     return G_TOKEN_STRING;
460 
461   gimp_plug_in_procedure_set_image_types (*proc, str);
462   g_free (str);
463 
464   if (! gimp_scanner_parse_int (scanner, (gint *) &n_args))
465     return G_TOKEN_INT;
466   if (! gimp_scanner_parse_int (scanner, (gint *) &n_return_vals))
467     return G_TOKEN_INT;
468 
469   for (i = 0; i < n_args; i++)
470     {
471       token = plug_in_proc_arg_deserialize (scanner, gimp, procedure, FALSE);
472       if (token != G_TOKEN_LEFT_PAREN)
473         return token;
474     }
475 
476   for (i = 0; i < n_return_vals; i++)
477     {
478       token = plug_in_proc_arg_deserialize (scanner, gimp, procedure, TRUE);
479       if (token != G_TOKEN_LEFT_PAREN)
480         return token;
481     }
482 
483   if (! gimp_scanner_parse_token (scanner, G_TOKEN_RIGHT_PAREN))
484     return G_TOKEN_RIGHT_PAREN;
485 
486   return G_TOKEN_LEFT_PAREN;
487 }
488 
489 static GTokenType
plug_in_menu_path_deserialize(GScanner * scanner,GimpPlugInProcedure * proc)490 plug_in_menu_path_deserialize (GScanner            *scanner,
491                                GimpPlugInProcedure *proc)
492 {
493   gchar *menu_path;
494 
495   if (! gimp_scanner_parse_token (scanner, G_TOKEN_LEFT_PAREN))
496     return G_TOKEN_LEFT_PAREN;
497 
498   if (! gimp_scanner_parse_token (scanner, G_TOKEN_SYMBOL) ||
499       GPOINTER_TO_INT (scanner->value.v_symbol) != MENU_PATH)
500     return G_TOKEN_SYMBOL;
501 
502   if (! gimp_scanner_parse_string (scanner, &menu_path))
503     return G_TOKEN_STRING;
504 
505   proc->menu_paths = g_list_append (proc->menu_paths, menu_path);
506 
507   if (! gimp_scanner_parse_token (scanner, G_TOKEN_RIGHT_PAREN))
508     return G_TOKEN_RIGHT_PAREN;
509 
510   return G_TOKEN_LEFT_PAREN;
511 }
512 
513 static GTokenType
plug_in_icon_deserialize(GScanner * scanner,GimpPlugInProcedure * proc)514 plug_in_icon_deserialize (GScanner            *scanner,
515                           GimpPlugInProcedure *proc)
516 {
517   GEnumClass   *enum_class;
518   GEnumValue   *enum_value;
519   GimpIconType  icon_type;
520   gint          icon_data_length;
521   gchar        *icon_name;
522   guint8       *icon_data;
523 
524   if (! gimp_scanner_parse_token (scanner, G_TOKEN_LEFT_PAREN))
525     return G_TOKEN_LEFT_PAREN;
526 
527   if (! gimp_scanner_parse_token (scanner, G_TOKEN_SYMBOL) ||
528       GPOINTER_TO_INT (scanner->value.v_symbol) != ICON)
529     return G_TOKEN_SYMBOL;
530 
531   enum_class = g_type_class_peek (GIMP_TYPE_ICON_TYPE);
532 
533   switch (g_scanner_peek_next_token (scanner))
534     {
535     case G_TOKEN_IDENTIFIER:
536       g_scanner_get_next_token (scanner);
537 
538       enum_value = g_enum_get_value_by_nick (G_ENUM_CLASS (enum_class),
539                                              scanner->value.v_identifier);
540       if (!enum_value)
541         enum_value = g_enum_get_value_by_name (G_ENUM_CLASS (enum_class),
542                                                scanner->value.v_identifier);
543 
544       if (!enum_value)
545         {
546           g_scanner_error (scanner,
547                            _("invalid value '%s' for icon type"),
548                            scanner->value.v_identifier);
549           return G_TOKEN_NONE;
550         }
551       break;
552 
553     case G_TOKEN_INT:
554       g_scanner_get_next_token (scanner);
555 
556       enum_value = g_enum_get_value (enum_class,
557                                      (gint) scanner->value.v_int64);
558 
559       if (!enum_value)
560         {
561           g_scanner_error (scanner,
562                            _("invalid value '%ld' for icon type"),
563                            (glong) scanner->value.v_int64);
564           return G_TOKEN_NONE;
565         }
566       break;
567 
568     default:
569       return G_TOKEN_IDENTIFIER;
570     }
571 
572   icon_type = enum_value->value;
573 
574   if (! gimp_scanner_parse_int (scanner, &icon_data_length))
575     return G_TOKEN_INT;
576 
577   switch (icon_type)
578     {
579     case GIMP_ICON_TYPE_ICON_NAME:
580     case GIMP_ICON_TYPE_IMAGE_FILE:
581       icon_data_length = -1;
582 
583       if (! gimp_scanner_parse_string_no_validate (scanner, &icon_name))
584         return G_TOKEN_STRING;
585 
586       icon_data = (guint8 *) icon_name;
587       break;
588 
589     case GIMP_ICON_TYPE_INLINE_PIXBUF:
590       if (icon_data_length < 0)
591         return G_TOKEN_STRING;
592 
593       if (! gimp_scanner_parse_data (scanner, icon_data_length, &icon_data))
594         return G_TOKEN_STRING;
595       break;
596     }
597 
598   gimp_plug_in_procedure_take_icon (proc, icon_type,
599                                     icon_data, icon_data_length);
600 
601   if (! gimp_scanner_parse_token (scanner, G_TOKEN_RIGHT_PAREN))
602     return G_TOKEN_RIGHT_PAREN;
603 
604   return G_TOKEN_LEFT_PAREN;
605 }
606 
607 static GTokenType
plug_in_file_proc_deserialize(GScanner * scanner,GimpPlugInProcedure * proc)608 plug_in_file_proc_deserialize (GScanner            *scanner,
609                                GimpPlugInProcedure *proc)
610 {
611   GTokenType token;
612   gint       symbol;
613 
614   if (! gimp_scanner_parse_token (scanner, G_TOKEN_LEFT_PAREN))
615     return G_TOKEN_LEFT_PAREN;
616 
617   if (! gimp_scanner_parse_token (scanner, G_TOKEN_SYMBOL))
618     return G_TOKEN_SYMBOL;
619 
620   symbol = GPOINTER_TO_INT (scanner->value.v_symbol);
621   if (symbol != LOAD_PROC && symbol != SAVE_PROC)
622     return G_TOKEN_SYMBOL;
623 
624   proc->file_proc = TRUE;
625 
626   g_scanner_set_scope (scanner, symbol);
627 
628   while (g_scanner_peek_next_token (scanner) == G_TOKEN_LEFT_PAREN)
629     {
630       token = g_scanner_get_next_token (scanner);
631 
632       if (token != G_TOKEN_LEFT_PAREN)
633         return token;
634 
635       if (! gimp_scanner_parse_token (scanner, G_TOKEN_SYMBOL))
636         return G_TOKEN_SYMBOL;
637 
638       symbol = GPOINTER_TO_INT (scanner->value.v_symbol);
639 
640       switch (symbol)
641         {
642         case EXTENSIONS:
643           {
644             gchar *extensions;
645 
646             if (! gimp_scanner_parse_string (scanner, &extensions))
647               return G_TOKEN_STRING;
648 
649             g_free (proc->extensions);
650             proc->extensions = extensions;
651           }
652           break;
653 
654         case PREFIXES:
655           {
656             gchar *prefixes;
657 
658             if (! gimp_scanner_parse_string (scanner, &prefixes))
659               return G_TOKEN_STRING;
660 
661             g_free (proc->prefixes);
662             proc->prefixes = prefixes;
663           }
664           break;
665 
666         case MAGICS:
667           {
668             gchar *magics;
669 
670             if (! gimp_scanner_parse_string_no_validate (scanner, &magics))
671               return G_TOKEN_STRING;
672 
673             g_free (proc->magics);
674             proc->magics = magics;
675           }
676           break;
677 
678         case PRIORITY:
679           {
680             gint priority;
681 
682             if (! gimp_scanner_parse_int (scanner, &priority))
683               return G_TOKEN_INT;
684 
685             gimp_plug_in_procedure_set_priority (proc, priority);
686           }
687           break;
688 
689         case MIME_TYPES:
690           {
691             gchar *mime_types;
692 
693             if (! gimp_scanner_parse_string (scanner, &mime_types))
694               return G_TOKEN_STRING;
695 
696             gimp_plug_in_procedure_set_mime_types (proc, mime_types);
697 
698             g_free (mime_types);
699           }
700           break;
701 
702         case HANDLES_URI:
703           gimp_plug_in_procedure_set_handles_uri (proc);
704           break;
705 
706         case HANDLES_RAW:
707           gimp_plug_in_procedure_set_handles_raw (proc);
708           break;
709 
710         case THUMB_LOADER:
711           {
712             gchar *thumb_loader;
713 
714             if (! gimp_scanner_parse_string (scanner, &thumb_loader))
715               return G_TOKEN_STRING;
716 
717             gimp_plug_in_procedure_set_thumb_loader (proc, thumb_loader);
718 
719             g_free (thumb_loader);
720           }
721           break;
722 
723         default:
724            return G_TOKEN_SYMBOL;
725         }
726       if (! gimp_scanner_parse_token (scanner, G_TOKEN_RIGHT_PAREN))
727         return G_TOKEN_RIGHT_PAREN;
728     }
729 
730   if (! gimp_scanner_parse_token (scanner, G_TOKEN_RIGHT_PAREN))
731     return G_TOKEN_RIGHT_PAREN;
732 
733   g_scanner_set_scope (scanner, PLUG_IN_DEF);
734 
735   return G_TOKEN_LEFT_PAREN;
736 }
737 
738 static GTokenType
plug_in_proc_arg_deserialize(GScanner * scanner,Gimp * gimp,GimpProcedure * procedure,gboolean return_value)739 plug_in_proc_arg_deserialize (GScanner      *scanner,
740                               Gimp          *gimp,
741                               GimpProcedure *procedure,
742                               gboolean       return_value)
743 {
744   GTokenType  token;
745   gint        arg_type;
746   gchar      *name = NULL;
747   gchar      *desc = NULL;
748   GParamSpec *pspec;
749 
750   if (! gimp_scanner_parse_token (scanner, G_TOKEN_LEFT_PAREN))
751     {
752       token = G_TOKEN_LEFT_PAREN;
753       goto error;
754     }
755 
756   if (! gimp_scanner_parse_token (scanner, G_TOKEN_SYMBOL) ||
757       GPOINTER_TO_INT (scanner->value.v_symbol) != PROC_ARG)
758     {
759       token = G_TOKEN_SYMBOL;
760       goto error;
761     }
762 
763   if (! gimp_scanner_parse_int (scanner, (gint *) &arg_type))
764     {
765       token = G_TOKEN_INT;
766       goto error;
767     }
768   if (! gimp_scanner_parse_string (scanner, &name))
769     {
770       token = G_TOKEN_STRING;
771       goto error;
772     }
773   if (! gimp_scanner_parse_string (scanner, &desc))
774     {
775       token = G_TOKEN_STRING;
776       goto error;
777     }
778 
779   if (! gimp_scanner_parse_token (scanner, G_TOKEN_RIGHT_PAREN))
780     {
781       token = G_TOKEN_RIGHT_PAREN;
782       goto error;
783     }
784 
785   token = G_TOKEN_LEFT_PAREN;
786 
787   pspec = gimp_pdb_compat_param_spec (gimp, arg_type, name, desc, NULL);
788 
789   if (return_value)
790     gimp_procedure_add_return_value (procedure, pspec);
791   else
792     gimp_procedure_add_argument (procedure, pspec);
793 
794  error:
795 
796   g_free (name);
797   g_free (desc);
798 
799   return token;
800 }
801 
802 static GTokenType
plug_in_locale_def_deserialize(GScanner * scanner,GimpPlugInDef * plug_in_def)803 plug_in_locale_def_deserialize (GScanner      *scanner,
804                                 GimpPlugInDef *plug_in_def)
805 {
806   gchar *domain_name;
807   gchar *domain_path   = NULL;
808   gchar *expanded_path = NULL;
809 
810   if (! gimp_scanner_parse_string (scanner, &domain_name))
811     return G_TOKEN_STRING;
812 
813   if (gimp_scanner_parse_string (scanner, &domain_path))
814     expanded_path = gimp_config_path_expand (domain_path, TRUE, NULL);
815 
816   gimp_plug_in_def_set_locale_domain (plug_in_def, domain_name, expanded_path);
817 
818   g_free (domain_name);
819   g_free (domain_path);
820   g_free (expanded_path);
821 
822   if (! gimp_scanner_parse_token (scanner, G_TOKEN_RIGHT_PAREN))
823     return G_TOKEN_RIGHT_PAREN;
824 
825   return G_TOKEN_LEFT_PAREN;
826 }
827 
828 static GTokenType
plug_in_help_def_deserialize(GScanner * scanner,GimpPlugInDef * plug_in_def)829 plug_in_help_def_deserialize (GScanner      *scanner,
830                               GimpPlugInDef *plug_in_def)
831 {
832   gchar *domain_name;
833   gchar *domain_uri;
834 
835   if (! gimp_scanner_parse_string (scanner, &domain_name))
836     return G_TOKEN_STRING;
837 
838   if (! gimp_scanner_parse_string (scanner, &domain_uri))
839     domain_uri = NULL;
840 
841   gimp_plug_in_def_set_help_domain (plug_in_def, domain_name, domain_uri);
842 
843   g_free (domain_name);
844   g_free (domain_uri);
845 
846   if (! gimp_scanner_parse_token (scanner, G_TOKEN_RIGHT_PAREN))
847     return G_TOKEN_RIGHT_PAREN;
848 
849   return G_TOKEN_LEFT_PAREN;
850 }
851 
852 static GTokenType
plug_in_has_init_deserialize(GScanner * scanner,GimpPlugInDef * plug_in_def)853 plug_in_has_init_deserialize (GScanner      *scanner,
854                               GimpPlugInDef *plug_in_def)
855 {
856   gimp_plug_in_def_set_has_init (plug_in_def, TRUE);
857 
858   if (! gimp_scanner_parse_token (scanner, G_TOKEN_RIGHT_PAREN))
859     return G_TOKEN_RIGHT_PAREN;
860 
861   return G_TOKEN_LEFT_PAREN;
862 }
863 
864 
865 /* serialize functions */
866 
867 gboolean
plug_in_rc_write(GSList * plug_in_defs,GFile * file,GError ** error)868 plug_in_rc_write (GSList  *plug_in_defs,
869                   GFile   *file,
870                   GError **error)
871 {
872   GimpConfigWriter *writer;
873   GEnumClass       *enum_class;
874   GSList           *list;
875 
876   writer = gimp_config_writer_new_gfile (file,
877                                          FALSE,
878                                          "GIMP pluginrc\n\n"
879                                          "This file can safely be removed and "
880                                          "will be automatically regenerated by "
881                                          "querying the installed plug-ins.",
882                                          error);
883   if (!writer)
884     return FALSE;
885 
886   enum_class = g_type_class_ref (GIMP_TYPE_ICON_TYPE);
887 
888   gimp_config_writer_open (writer, "protocol-version");
889   gimp_config_writer_printf (writer, "%d", GIMP_PROTOCOL_VERSION);
890   gimp_config_writer_close (writer);
891 
892   gimp_config_writer_open (writer, "file-version");
893   gimp_config_writer_printf (writer, "%d", PLUG_IN_RC_FILE_VERSION);
894   gimp_config_writer_close (writer);
895 
896   gimp_config_writer_linefeed (writer);
897 
898   for (list = plug_in_defs; list; list = list->next)
899     {
900       GimpPlugInDef *plug_in_def = list->data;
901 
902       if (plug_in_def->procedures)
903         {
904           GSList *list2;
905           gchar  *path;
906 
907           path = gimp_file_get_config_path (plug_in_def->file, NULL);
908           if (! path)
909             continue;
910 
911           gimp_config_writer_open (writer, "plug-in-def");
912           gimp_config_writer_string (writer, path);
913           gimp_config_writer_printf (writer, "%"G_GINT64_FORMAT,
914                                      plug_in_def->mtime);
915 
916           g_free (path);
917 
918           for (list2 = plug_in_def->procedures; list2; list2 = list2->next)
919             {
920               GimpPlugInProcedure *proc      = list2->data;
921               GimpProcedure       *procedure = GIMP_PROCEDURE (proc);
922               GEnumValue          *enum_value;
923               GList               *list3;
924               gint                 i;
925 
926               if (proc->installed_during_init)
927                 continue;
928 
929               gimp_config_writer_open (writer, "proc-def");
930               gimp_config_writer_printf (writer, "\"%s\" %d",
931                                          procedure->original_name,
932                                          procedure->proc_type);
933               gimp_config_writer_linefeed (writer);
934               gimp_config_writer_string (writer, procedure->blurb);
935               gimp_config_writer_linefeed (writer);
936               gimp_config_writer_string (writer, procedure->help);
937               gimp_config_writer_linefeed (writer);
938               gimp_config_writer_string (writer, procedure->author);
939               gimp_config_writer_linefeed (writer);
940               gimp_config_writer_string (writer, procedure->copyright);
941               gimp_config_writer_linefeed (writer);
942               gimp_config_writer_string (writer, procedure->date);
943               gimp_config_writer_linefeed (writer);
944               gimp_config_writer_string (writer, proc->menu_label);
945               gimp_config_writer_linefeed (writer);
946 
947               gimp_config_writer_printf (writer, "%d",
948                                          g_list_length (proc->menu_paths));
949               for (list3 = proc->menu_paths; list3; list3 = list3->next)
950                 {
951                   gimp_config_writer_open (writer, "menu-path");
952                   gimp_config_writer_string (writer, list3->data);
953                   gimp_config_writer_close (writer);
954                 }
955 
956               gimp_config_writer_open (writer, "icon");
957               enum_value = g_enum_get_value (enum_class, proc->icon_type);
958               gimp_config_writer_identifier (writer, enum_value->value_nick);
959               gimp_config_writer_printf (writer, "%d",
960                                          proc->icon_data_length);
961 
962               switch (proc->icon_type)
963                 {
964                 case GIMP_ICON_TYPE_ICON_NAME:
965                 case GIMP_ICON_TYPE_IMAGE_FILE:
966                   gimp_config_writer_string (writer, (gchar *) proc->icon_data);
967                   break;
968 
969                 case GIMP_ICON_TYPE_INLINE_PIXBUF:
970                   gimp_config_writer_data (writer, proc->icon_data_length,
971                                            proc->icon_data);
972                   break;
973                 }
974 
975               gimp_config_writer_close (writer);
976 
977               if (proc->file_proc)
978                 {
979                   gimp_config_writer_open (writer,
980                                            proc->image_types ?
981                                            "save-proc" : "load-proc");
982 
983                   if (proc->extensions && *proc->extensions)
984                     {
985                       gimp_config_writer_open (writer, "extensions");
986                       gimp_config_writer_string (writer, proc->extensions);
987                       gimp_config_writer_close (writer);
988                     }
989 
990                   if (proc->prefixes && *proc->prefixes)
991                     {
992                       gimp_config_writer_open (writer, "prefixes");
993                       gimp_config_writer_string (writer, proc->prefixes);
994                       gimp_config_writer_close (writer);
995                     }
996 
997                   if (proc->magics && *proc->magics)
998                     {
999                       gimp_config_writer_open (writer, "magics");
1000                       gimp_config_writer_string (writer, proc->magics);
1001                       gimp_config_writer_close (writer);
1002                     }
1003 
1004                   if (proc->priority)
1005                     {
1006                       gimp_config_writer_open (writer, "priority");
1007                       gimp_config_writer_printf (writer, "%d", proc->priority);
1008                       gimp_config_writer_close (writer);
1009                     }
1010 
1011                   if (proc->mime_types && *proc->mime_types)
1012                     {
1013                       gimp_config_writer_open (writer, "mime-types");
1014                       gimp_config_writer_string (writer, proc->mime_types);
1015                       gimp_config_writer_close (writer);
1016                     }
1017 
1018                   if (proc->priority)
1019                     {
1020                       gimp_config_writer_open (writer, "priority");
1021                       gimp_config_writer_printf (writer, "%d", proc->priority);
1022                       gimp_config_writer_close (writer);
1023                     }
1024 
1025                   if (proc->handles_uri)
1026                     {
1027                       gimp_config_writer_open (writer, "handles-uri");
1028                       gimp_config_writer_close (writer);
1029                     }
1030 
1031                   if (proc->handles_raw && ! proc->image_types)
1032                     {
1033                       gimp_config_writer_open (writer, "handles-raw");
1034                       gimp_config_writer_close (writer);
1035                     }
1036 
1037                   if (proc->thumb_loader)
1038                     {
1039                       gimp_config_writer_open (writer, "thumb-loader");
1040                       gimp_config_writer_string (writer, proc->thumb_loader);
1041                       gimp_config_writer_close (writer);
1042                     }
1043 
1044                   gimp_config_writer_close (writer);
1045                 }
1046 
1047               gimp_config_writer_linefeed (writer);
1048 
1049               gimp_config_writer_string (writer, proc->image_types);
1050               gimp_config_writer_linefeed (writer);
1051 
1052               gimp_config_writer_printf (writer, "%d %d",
1053                                          procedure->num_args,
1054                                          procedure->num_values);
1055 
1056               for (i = 0; i < procedure->num_args; i++)
1057                 {
1058                   GParamSpec *pspec = procedure->args[i];
1059 
1060                   gimp_config_writer_open (writer, "proc-arg");
1061                   gimp_config_writer_printf (writer, "%d",
1062                                              gimp_pdb_compat_arg_type_from_gtype (G_PARAM_SPEC_VALUE_TYPE (pspec)));
1063 
1064                   gimp_config_writer_string (writer,
1065                                              g_param_spec_get_name (pspec));
1066                   gimp_config_writer_string (writer,
1067                                              g_param_spec_get_blurb (pspec));
1068 
1069                   gimp_config_writer_close (writer);
1070                 }
1071 
1072               for (i = 0; i < procedure->num_values; i++)
1073                 {
1074                   GParamSpec *pspec = procedure->values[i];
1075 
1076                   gimp_config_writer_open (writer, "proc-arg");
1077                   gimp_config_writer_printf (writer, "%d",
1078                                              gimp_pdb_compat_arg_type_from_gtype (G_PARAM_SPEC_VALUE_TYPE (pspec)));
1079 
1080                   gimp_config_writer_string (writer,
1081                                              g_param_spec_get_name (pspec));
1082                   gimp_config_writer_string (writer,
1083                                              g_param_spec_get_blurb (pspec));
1084 
1085                   gimp_config_writer_close (writer);
1086                 }
1087 
1088               gimp_config_writer_close (writer);
1089             }
1090 
1091           if (plug_in_def->locale_domain_name)
1092             {
1093               gimp_config_writer_open (writer, "locale-def");
1094               gimp_config_writer_string (writer,
1095                                          plug_in_def->locale_domain_name);
1096 
1097               if (plug_in_def->locale_domain_path)
1098                 {
1099                   path = gimp_config_path_unexpand (plug_in_def->locale_domain_path,
1100                                                     TRUE, NULL);
1101                   if (path)
1102                     {
1103                       gimp_config_writer_string (writer, path);
1104                       g_free (path);
1105                     }
1106                 }
1107 
1108               gimp_config_writer_close (writer);
1109             }
1110 
1111           if (plug_in_def->help_domain_name)
1112             {
1113               gimp_config_writer_open (writer, "help-def");
1114               gimp_config_writer_string (writer,
1115                                          plug_in_def->help_domain_name);
1116 
1117               if (plug_in_def->help_domain_uri)
1118                 gimp_config_writer_string (writer,
1119                                            plug_in_def->help_domain_uri);
1120 
1121              gimp_config_writer_close (writer);
1122             }
1123 
1124           if (plug_in_def->has_init)
1125             {
1126               gimp_config_writer_open (writer, "has-init");
1127               gimp_config_writer_close (writer);
1128             }
1129 
1130           gimp_config_writer_close (writer);
1131         }
1132     }
1133 
1134   g_type_class_unref (enum_class);
1135 
1136   return gimp_config_writer_finish (writer, "end of pluginrc", error);
1137 }
1138