1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2 
3 /*
4  * GImageView
5  * Copyright (C) 2001 Takuro Ashie
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 2 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, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  *
21  * $Id: spi.c,v 1.8 2003/06/13 09:43:02 makeinu Exp $
22  */
23 
24 #include "spi.h"
25 
26 #ifdef ENABLE_SPI
27 
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include "fileutil.h"
32 #include "gfileutil.h"
33 #include "prefs_spi.h"
34 
35 #ifdef G_PLATFORM_WIN32
36 static
peimage_resolve(PE_image * image,const char * symbol_name)37 void* peimage_resolve (PE_image* image, const char* symbol_name)
38 {
39    void* symbol;
40    if (g_module_symbol (image, symbol_name, &symbol))
41       return symbol;
42    else
43       return NULL;
44 }
45 #endif
46 
47 static void         spi_clear_search_dir_list    (void);
48 static void         spi_create_search_dir_list   (void);
49 static void         spi_search_directory         (const gchar *dirname);
50 static gboolean     spi_regist                   (PE_image    *pe);
51 static SusiePlugin *spi_regist_import_filter     (PE_image    *pe);
52 static SusiePlugin *spi_regist_export_filter     (PE_image    *pe);
53 static SusiePlugin *spi_regist_archive_extractor (PE_image    *pe);
54 
55 
56 const char *spi_errormsg[] = {
57   /* -1: Unimplemented */
58   "Success",
59   "Callback returned non-zero",
60   "Unknown format",
61   "Data broken",
62   "No enough memory",
63   "Memory error",
64   "File read error",
65   "Reserved",
66   "Internal error"
67 };
68 int spi_errormsg_num = sizeof (spi_errormsg) / sizeof (char *);
69 
70 
71 static gboolean spi_inited               = FALSE;
72 static GList *spi_search_dir_list        = NULL;
73 static GList *spi_import_filter_list     = NULL;
74 static GList *spi_export_filter_list     = NULL;
75 static GList *spi_archive_extractor_list = NULL;
76 
77 
78 /*****************************************************************************
79  *
80  *   Private functions.
81  *
82  *****************************************************************************/
83 static void
spi_clear_search_dir_list(void)84 spi_clear_search_dir_list (void)
85 {
86    g_list_foreach (spi_search_dir_list, (GFunc) g_free, NULL);
87    g_list_free (spi_search_dir_list);
88    spi_search_dir_list = NULL;
89 }
90 
91 
92 static void
spi_create_search_dir_list(void)93 spi_create_search_dir_list (void)
94 {
95    const gchar *dirlist;
96    gchar **dirs;
97    gint i;
98 
99    spi_clear_search_dir_list ();
100 
101    if (gimv_prefs_spi_get_use_default_dirlist ())
102       dirlist = SPI_DEFAULT_SEARCH_DIR_LIST;
103    else
104       dirlist = gimv_prefs_spi_get_dirconf ();
105 
106    if (!dirlist || !*dirlist) return;
107 
108    dirs = g_strsplit (dirlist, ",", -1);
109 
110    for (i = 0; dirs && dirs[i]; i++) {
111       if (*dirs[i])
112          spi_search_dir_list = g_list_append (spi_search_dir_list,
113                                               g_strdup (dirs[i]));
114    }
115 
116    g_strfreev (dirs);
117 }
118 
119 
120 static void
spi_search_directory(const gchar * dirname)121 spi_search_directory (const gchar *dirname)
122 {
123    GList *filelist = NULL, *node;
124 
125    g_return_if_fail (dirname);
126    if (!isdir (dirname)) return;
127 
128    get_dir (dirname, GETDIR_FOLLOW_SYMLINK, &filelist, NULL);
129    if (!filelist) return;
130 
131    node = filelist;
132 
133    while (node) {
134       gchar *filename = node->data;
135       gboolean success;
136       gint len;
137       PE_image *pe;
138 
139       node = g_list_next (node);
140 
141       len = strlen (filename);
142       if (len < 4 || strcasecmp (filename + len - 4, ".spi")) continue;
143 
144       g_print ("PluginName: %s\n", filename);
145 
146       pe = peimage_create ();
147       if (!peimage_load (pe, filename)) {
148          peimage_destroy (pe);
149          g_print ("peimage_load() failed: %s\n", filename);
150          continue;
151       }
152 
153       success = spi_regist (pe);
154       if (success) {
155          /* hoge */
156       } else {
157          peimage_destroy(pe);
158       }
159    }
160 
161    g_list_foreach (filelist, (GFunc) g_free, NULL);
162    g_list_free (filelist);
163 }
164 
165 
166 static gboolean
spi_regist(PE_image * pe)167 spi_regist (PE_image *pe)
168 {
169    gchar buf[256];
170    gboolean success;
171    GetPluginInfoFunc get_plugin_info;
172    SusiePlugin *plugin;
173 
174    g_return_val_if_fail (pe, FALSE);
175 
176    get_plugin_info = peimage_resolve (pe, "GetPluginInfo");
177    if (!get_plugin_info) {
178       g_print ("Cannot resolve GetPluginInfo.\n");
179       goto ERROR;
180    }
181 
182    success = get_plugin_info (0, buf, 256);
183    if (!success) {
184       g_print ("GetPluginInfo returns 0\n");
185       goto ERROR;
186    }
187 
188    switch (buf[2]) {
189    case 'I':
190       g_print ("Detected as Import filter.\n");
191       plugin = spi_regist_import_filter (pe);
192       break;
193 
194    case 'X':
195       g_print ("Export filter is not supported yet.\n");
196       plugin = spi_regist_export_filter (pe);
197       break;
198 
199    case 'A':
200       g_print ("Archiver extractor is not supported yet.\n");
201       plugin = spi_regist_archive_extractor (pe);
202       break;
203 
204    default:
205       g_print ("Unknown susie plugin type %c.\n", buf[2]);
206       plugin = NULL;
207       break;
208    }
209 
210    if (!plugin) goto ERROR;
211 
212    plugin->pe = pe;
213    plugin->get_plugin_info = get_plugin_info;
214    success = plugin->get_plugin_info (1, buf, 256);
215    if (success) {
216       plugin->description = g_strdup (buf);
217       g_print ("description: %s\n\n", plugin->description);
218    } else {
219       plugin->description = NULL;
220    }
221 
222    /* FIXME */
223    plugin->formats = NULL;
224 
225 
226    return TRUE;
227 
228 ERROR:
229    return FALSE;
230 }
231 
232 
233 static SusiePlugin *
spi_regist_import_filter(PE_image * pe)234 spi_regist_import_filter (PE_image *pe)
235 {
236    SpiImportFilter *loader;
237 
238    g_return_val_if_fail (pe, NULL);
239 
240    loader = g_new0 (SpiImportFilter, 1);
241 
242    loader->is_supported = peimage_resolve (pe, "IsSupported");
243    if (!loader->is_supported) {
244       g_print ("Cannot resolve IsSupported.\n");
245       goto ERROR;
246    }
247 
248    loader->get_pic_info = peimage_resolve (pe, "GetPictureInfo");
249    if (!loader->get_pic_info) {
250       g_print ("Cannot resolve GetPictureInfo.\n");
251       goto ERROR;
252    }
253 
254    loader->get_pic = peimage_resolve (pe, "GetPicture");
255    if (!loader->get_pic) {
256       g_print ("Cannot resolve GetPicture.\n");
257       goto ERROR;
258    }
259 
260    spi_import_filter_list = g_list_append (spi_import_filter_list, loader);
261 
262    return (SusiePlugin *) loader;
263 
264 ERROR:
265    g_free (loader);
266    return NULL;
267 }
268 
269 
270 static SusiePlugin *
spi_regist_export_filter(PE_image * pe)271 spi_regist_export_filter (PE_image *pe)
272 {
273    return NULL;
274 }
275 
276 
277 static SusiePlugin *
spi_regist_archive_extractor(PE_image * pe)278 spi_regist_archive_extractor (PE_image *pe)
279 {
280    SpiArchiveExtractor *extractor;
281 
282    g_return_val_if_fail (pe, NULL);
283 
284    extractor = g_new0 (SpiArchiveExtractor, 1);
285 
286    extractor->is_supported = peimage_resolve (pe, "IsSupported");
287    if (!extractor->is_supported) {
288       g_print ("Cannot resolve IsSupported.\n");
289       goto ERROR;
290    }
291 
292    extractor->get_archive_info = peimage_resolve (pe, "GetArchiveInfo");
293    if (!extractor->get_archive_info) {
294       g_print ("Cannot resolve GetArchiveInfo.\n");
295       goto ERROR;
296    }
297 
298    extractor->get_file_info = peimage_resolve (pe, "GetFileInfo");
299    if (!extractor->get_file_info) {
300       g_print ("Cannot resolve GetFileInfo.\n");
301       goto ERROR;
302    }
303 
304    extractor->get_file = peimage_resolve (pe, "GetFile");
305    if (!extractor->get_file) {
306       g_print ("Cannot resolve GetFile.\n");
307       goto ERROR;
308    }
309 
310    spi_archive_extractor_list = g_list_append (spi_archive_extractor_list,
311                                                extractor);
312 
313    return (SusiePlugin *) extractor;
314 
315 ERROR:
316    g_free (extractor);
317    return NULL;
318 }
319 
320 
321 
322 /*****************************************************************************
323  *
324  *   Public functions.
325  *
326  *****************************************************************************/
327 void
spi_init()328 spi_init ()
329 {
330    GList *list;
331 
332    spi_create_search_dir_list ();
333 
334    /* load spi from disk */
335    list = g_list_last (spi_search_dir_list);
336    for (; list; list = g_list_previous (list)) {
337       gchar *dir = list->data;
338 
339       if (dir && *dir)
340          spi_search_directory (dir);
341    }
342 
343    spi_inited = TRUE;
344 }
345 
346 
347 GList *
spi_get_search_dir_list(void)348 spi_get_search_dir_list (void)
349 {
350    if (!spi_inited)
351       spi_init();
352    return spi_search_dir_list;
353 }
354 
355 
356 GList *
spi_get_import_filter_list(void)357 spi_get_import_filter_list (void)
358 {
359    if (!spi_inited)
360       spi_init();
361    return spi_import_filter_list;
362 }
363 
364 
365 GList *
spi_get_export_filter_list(void)366 spi_get_export_filter_list (void)
367 {
368    if (!spi_inited)
369       spi_init();
370    return spi_export_filter_list;
371 }
372 
373 
374 GList *
spi_get_archive_extractor_list(void)375 spi_get_archive_extractor_list (void)
376 {
377    if (!spi_inited)
378       spi_init();
379    return spi_archive_extractor_list;
380 }
381 
382 #endif /* ENABLE_SPI */
383