From cc2a076df5f523352452138ea80ae3373af46d01 Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Fri, 11 May 2007 18:50:35 +0000 Subject: [PATCH] app/file/Makefile.am app/file/file-procedure.[ch] split functions dealing 2007-05-11 Sven Neumann * app/file/Makefile.am * app/file/file-procedure.[ch] * app/file/file-utils.[ch]: split functions dealing with file procedures into their own file and renamed them. * app/file/file-open.c * app/dialogs/file-save-dialog.c * app/actions/file-commands.c * app/widgets/gimpthumbbox.c * app/widgets/gimpdnd-xds.c * app/widgets/gimpimagepropview.c * tools/pdbgen/pdb/fileops.pdb: changed accordingly * app/pdb/fileops_cmds.c: regenerated. svn path=/trunk/; revision=22474 --- ChangeLog | 17 + app/actions/file-commands.c | 5 +- app/dialogs/file-save-dialog.c | 15 +- app/file/Makefile.am | 2 + app/file/file-open.c | 9 +- app/file/file-procedure.c | 575 ++++++++++++++++++++++++++++++++ app/file/file-procedure.h | 34 ++ app/file/file-utils.c | 541 +----------------------------- app/file/file-utils.h | 32 +- app/pdb/fileops_cmds.c | 5 +- app/widgets/gimpdnd-xds.c | 5 +- app/widgets/gimpimagepropview.c | 3 +- app/widgets/gimpthumbbox.c | 5 +- tools/pdbgen/pdb/fileops.pdb | 5 +- 14 files changed, 678 insertions(+), 575 deletions(-) create mode 100644 app/file/file-procedure.c create mode 100644 app/file/file-procedure.h diff --git a/ChangeLog b/ChangeLog index 399c3f08cb..b9062fdf1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2007-05-11 Sven Neumann + + * app/file/Makefile.am + * app/file/file-procedure.[ch] + * app/file/file-utils.[ch]: split functions dealing with file + procedures into their own file and renamed them. + + * app/file/file-open.c + * app/dialogs/file-save-dialog.c + * app/actions/file-commands.c + * app/widgets/gimpthumbbox.c + * app/widgets/gimpdnd-xds.c + * app/widgets/gimpimagepropview.c + * tools/pdbgen/pdb/fileops.pdb: changed accordingly + + * app/pdb/fileops_cmds.c: regenerated. + 2007-05-11 Karine Delvare * plug-ins/common/illusion.c: use the new preview transform function, diff --git a/app/actions/file-commands.c b/app/actions/file-commands.c index 3036402a7c..eeec5d0995 100644 --- a/app/actions/file-commands.c +++ b/app/actions/file-commands.c @@ -37,6 +37,7 @@ #include "plug-in/gimppluginmanager.h" #include "file/file-open.h" +#include "file/file-procedure.h" #include "file/file-save.h" #include "file/file-utils.h" @@ -211,8 +212,8 @@ file_save_cmd_callback (GtkAction *action, if (uri && ! save_proc) save_proc = - file_utils_find_proc (image->gimp->plug_in_manager->save_procs, - uri, NULL); + file_procedure_find (image->gimp->plug_in_manager->save_procs, + uri, NULL); if (uri && save_proc) { diff --git a/app/dialogs/file-save-dialog.c b/app/dialogs/file-save-dialog.c index 0677da45c2..8472e96a02 100644 --- a/app/dialogs/file-save-dialog.c +++ b/app/dialogs/file-save-dialog.c @@ -34,6 +34,7 @@ #include "plug-in/gimppluginmanager.h" #include "plug-in/gimppluginprocedure.h" +#include "file/file-procedure.h" #include "file/file-save.h" #include "file/file-utils.h" @@ -194,10 +195,10 @@ file_save_dialog_check_uri (GtkWidget *save_dialog, basename = file_utils_uri_display_basename(uri); save_proc = dialog->file_proc; - uri_proc = file_utils_find_proc (gimp->plug_in_manager->save_procs, - uri, NULL); - basename_proc = file_utils_find_proc (gimp->plug_in_manager->save_procs, - basename, NULL); + uri_proc = file_procedure_find (gimp->plug_in_manager->save_procs, + uri, NULL); + basename_proc = file_procedure_find (gimp->plug_in_manager->save_procs, + basename, NULL); #ifdef DEBUG_SPEW g_print ("\n\n%s: URI = %s\n", @@ -256,10 +257,10 @@ file_save_dialog_check_uri (GtkWidget *save_dialog, uri = ext_uri; basename = ext_basename; - uri_proc = file_utils_find_proc (gimp->plug_in_manager->save_procs, + uri_proc = file_procedure_find (gimp->plug_in_manager->save_procs, uri, NULL); - basename_proc = file_utils_find_proc (gimp->plug_in_manager->save_procs, - basename, NULL); + basename_proc = file_procedure_find (gimp->plug_in_manager->save_procs, + basename, NULL); utf8 = g_filename_to_utf8 (basename, -1, NULL, NULL, NULL); gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (save_dialog), diff --git a/app/file/Makefile.am b/app/file/Makefile.am index b8bf44efca..cad619e474 100644 --- a/app/file/Makefile.am +++ b/app/file/Makefile.am @@ -17,6 +17,8 @@ INCLUDES = \ libappfile_a_SOURCES = \ file-open.c \ file-open.h \ + file-procedure.c \ + file-procedure.h \ file-save.c \ file-save.h \ file-utils.c \ diff --git a/app/file/file-open.c b/app/file/file-open.c index 65fa2e3230..b0b3446ef2 100644 --- a/app/file/file-open.c +++ b/app/file/file-open.c @@ -64,6 +64,7 @@ #include "file-open.h" +#include "file-procedure.h" #include "file-utils.h" #include "gimprecentlist.h" @@ -106,8 +107,8 @@ file_open_image (Gimp *gimp, *status = GIMP_PDB_EXECUTION_ERROR; if (! file_proc) - file_proc = file_utils_find_proc (gimp->plug_in_manager->load_procs, - uri, error); + file_proc = file_procedure_find (gimp->plug_in_manager->load_procs, uri, + error); if (! file_proc) return NULL; @@ -213,8 +214,8 @@ file_open_thumbnail (Gimp *gimp, *image_width = 0; *image_height = 0; - file_proc = file_utils_find_proc (gimp->plug_in_manager->load_procs, - uri, NULL); + file_proc = file_procedure_find (gimp->plug_in_manager->load_procs, uri, + NULL); if (! file_proc || ! file_proc->thumb_loader) return NULL; diff --git a/app/file/file-procedure.c b/app/file/file-procedure.c new file mode 100644 index 0000000000..2f08a342da --- /dev/null +++ b/app/file/file-procedure.c @@ -0,0 +1,575 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995, 1996, 1997 Spencer Kimball and Peter Mattis + * Copyright (C) 1997 Josh MacDonald + * + * file-procedure.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include +#include +#include + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#include + +#include "libgimpbase/gimpbase.h" + +#include "core/core-types.h" + +#include "plug-in/gimppluginprocedure.h" + +#include "file-procedure.h" +#include "file-utils.h" + +#include "gimp-intl.h" + + +typedef enum +{ + FILE_MATCH_NONE, + FILE_MATCH_MAGIC, + FILE_MATCH_SIZE +} FileMatchType; + + +/* local function prototypes */ + +static GimpPlugInProcedure * file_proc_find_by_prefix (GSList *procs, + const gchar *uri, + gboolean skip_magic); +static GimpPlugInProcedure * file_proc_find_by_extension (GSList *procs, + const gchar *uri, + gboolean skip_magic); +static GimpPlugInProcedure * file_proc_find_by_name (GSList *procs, + const gchar *uri, + gboolean skip_magic); + +static void file_convert_string (const gchar *instr, + gchar *outmem, + gint maxmem, + gint *nmem); +static FileMatchType file_check_single_magic (const gchar *offset, + const gchar *type, + const gchar *value, + const guchar *file_head, + gint headsize, + FILE *ifp); +static FileMatchType file_check_magic_list (GSList *magics_list, + const guchar *head, + gint headsize, + FILE *ifp); + + +/* public functions */ + +GimpPlugInProcedure * +file_procedure_find (GSList *procs, + const gchar *uri, + GError **error) +{ + GimpPlugInProcedure *file_proc; + GSList *all_procs = procs; + gchar *filename; + + g_return_val_if_fail (procs != NULL, NULL); + g_return_val_if_fail (uri != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + /* First, check magicless prefixes/suffixes */ + file_proc = file_proc_find_by_name (all_procs, uri, TRUE); + + if (file_proc) + return file_proc; + + filename = file_utils_filename_from_uri (uri); + + /* Then look for magics */ + if (filename) + { + GimpPlugInProcedure *size_matched_proc = NULL; + FILE *ifp = NULL; + gint head_size = -2; + gint size_match_count = 0; + guchar head[256]; + + while (procs) + { + file_proc = procs->data; + procs = procs->next; + + if (file_proc->magics_list) + { + if (head_size == -2) + { + head_size = 0; + + if ((ifp = g_fopen (filename, "rb")) != NULL) + { + head_size = fread ((gchar *) head, 1, sizeof (head), ifp); + } + else + { + g_set_error (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), + g_strerror (errno)); + } + } + + if (head_size >= 4) + { + FileMatchType match_val; + + match_val = file_check_magic_list (file_proc->magics_list, + head, head_size, + ifp); + + if (match_val == FILE_MATCH_SIZE) + { + /* Use it only if no other magic matches */ + size_match_count++; + size_matched_proc = file_proc; + } + else if (match_val != FILE_MATCH_NONE) + { + fclose (ifp); + g_free (filename); + + return file_proc; + } + } + } + } + + if (ifp) + { + if (ferror (ifp)) + g_set_error (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), + g_strerror (errno)); + + fclose (ifp); + } + + g_free (filename); + + if (size_match_count == 1) + return size_matched_proc; + } + + /* As a last resort, try matching by name */ + file_proc = file_proc_find_by_name (all_procs, uri, FALSE); + + if (file_proc) + { + /* we found a procedure, clear error that might have been set */ + g_clear_error (error); + } + else + { + /* set an error message unless one was already set */ + if (error && *error == NULL) + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, + _("Unknown file type")); + } + + return file_proc; +} + +GimpPlugInProcedure * +file_procedure_find_by_prefix (GSList *procs, + const gchar *uri) +{ + g_return_val_if_fail (uri != NULL, NULL); + + return file_proc_find_by_prefix (procs, uri, FALSE); +} + +GimpPlugInProcedure * +file_procedure_find_by_extension (GSList *procs, + const gchar *uri) +{ + g_return_val_if_fail (uri != NULL, NULL); + + return file_proc_find_by_extension (procs, uri, FALSE); +} + + +/* private functions */ + +static GimpPlugInProcedure * +file_proc_find_by_prefix (GSList *procs, + const gchar *uri, + gboolean skip_magic) +{ + GSList *p; + + for (p = procs; p; p = g_slist_next (p)) + { + GimpPlugInProcedure *proc = p->data; + GSList *prefixes; + + if (skip_magic && proc->magics_list) + continue; + + for (prefixes = proc->prefixes_list; + prefixes; + prefixes = g_slist_next (prefixes)) + { + if (g_str_has_prefix (uri, prefixes->data)) + return proc; + } + } + + return NULL; +} + +static GimpPlugInProcedure * +file_proc_find_by_extension (GSList *procs, + const gchar *uri, + gboolean skip_magic) +{ + GSList *p; + const gchar *ext; + + ext = strrchr (uri, '.'); + + if (ext) + ext++; + + for (p = procs; p; p = g_slist_next (p)) + { + GimpPlugInProcedure *proc = p->data; + GSList *extensions; + + for (extensions = proc->extensions_list; + ext && extensions; + extensions = g_slist_next (extensions)) + { + const gchar *p1 = ext; + const gchar *p2 = extensions->data; + + if (skip_magic && proc->magics_list) + continue; + + while (*p1 && *p2) + { + if (g_ascii_tolower (*p1) != g_ascii_tolower (*p2)) + break; + + p1++; + p2++; + } + + if (!(*p1) && !(*p2)) + return proc; + } + } + + return NULL; +} + +static GimpPlugInProcedure * +file_proc_find_by_name (GSList *procs, + const gchar *uri, + gboolean skip_magic) +{ + GimpPlugInProcedure *proc; + + proc = file_proc_find_by_prefix (procs, uri, skip_magic); + + if (! proc) + proc = file_proc_find_by_extension (procs, uri, skip_magic); + + return proc; +} + + +static void +file_convert_string (const gchar *instr, + gchar *outmem, + gint maxmem, + gint *nmem) +{ + /* Convert a string in C-notation to array of char */ + const guchar *uin = (const guchar *) instr; + guchar *uout = (guchar *) outmem; + guchar tmp[5], *tmpptr; + guint k; + + while ((*uin != '\0') && ((((gchar *) uout) - outmem) < maxmem)) + { + if (*uin != '\\') /* Not an escaped character ? */ + { + *(uout++) = *(uin++); + continue; + } + + if (*(++uin) == '\0') + { + *(uout++) = '\\'; + break; + } + + switch (*uin) + { + case '0': case '1': case '2': case '3': /* octal */ + for (tmpptr = tmp; (tmpptr - tmp) <= 3;) + { + *(tmpptr++) = *(uin++); + if ( (*uin == '\0') || (!g_ascii_isdigit (*uin)) + || (*uin == '8') || (*uin == '9')) + break; + } + + *tmpptr = '\0'; + sscanf ((gchar *) tmp, "%o", &k); + *(uout++) = k; + break; + + case 'a': *(uout++) = '\a'; uin++; break; + case 'b': *(uout++) = '\b'; uin++; break; + case 't': *(uout++) = '\t'; uin++; break; + case 'n': *(uout++) = '\n'; uin++; break; + case 'v': *(uout++) = '\v'; uin++; break; + case 'f': *(uout++) = '\f'; uin++; break; + case 'r': *(uout++) = '\r'; uin++; break; + + default : *(uout++) = *(uin++); break; + } + } + + *nmem = ((gchar *) uout) - outmem; +} + +static FileMatchType +file_check_single_magic (const gchar *offset, + const gchar *type, + const gchar *value, + const guchar *file_head, + gint headsize, + FILE *ifp) + +{ + FileMatchType found = FILE_MATCH_NONE; + glong offs; + gulong num_testval; + gulong num_operatorval; + gint numbytes, k; + const gchar *num_operator_ptr; + gchar num_operator; + + /* Check offset */ + if (sscanf (offset, "%ld", &offs) != 1) + return FILE_MATCH_NONE; + + /* Check type of test */ + num_operator_ptr = NULL; + num_operator = '\0'; + + if (g_str_has_prefix (type, "byte")) + { + numbytes = 1; + num_operator_ptr = type + strlen ("byte"); + } + else if (g_str_has_prefix (type, "short")) + { + numbytes = 2; + num_operator_ptr = type + strlen ("short"); + } + else if (g_str_has_prefix (type, "long")) + { + numbytes = 4; + num_operator_ptr = type + strlen ("long"); + } + else if (g_str_has_prefix (type, "size")) + { + numbytes = 5; + } + else if (strcmp (type, "string") == 0) + { + numbytes = 0; + } + else + { + return FILE_MATCH_NONE; + } + + /* Check numerical operator value if present */ + if (num_operator_ptr && (*num_operator_ptr == '&')) + { + if (g_ascii_isdigit (num_operator_ptr[1])) + { + if (num_operator_ptr[1] != '0') /* decimal */ + sscanf (num_operator_ptr+1, "%lu", &num_operatorval); + else if (num_operator_ptr[2] == 'x') /* hexadecimal */ + sscanf (num_operator_ptr+3, "%lx", &num_operatorval); + else /* octal */ + sscanf (num_operator_ptr+2, "%lo", &num_operatorval); + + num_operator = *num_operator_ptr; + } + } + + if (numbytes > 0) /* Numerical test ? */ + { + gchar num_test = '='; + gulong fileval = 0; + + /* Check test value */ + if ((value[0] == '>') || (value[0] == '<')) + { + num_test = value[0]; + value++; + } + + errno = 0; + num_testval = strtol (value, NULL, 0); + + if (errno != 0) + return FILE_MATCH_NONE; + + if (numbytes == 5) /* Check for file size ? */ + { + struct stat buf; + + if (fstat (fileno (ifp), &buf) < 0) + return FILE_MATCH_NONE; + + fileval = buf.st_size; + } + else if (offs >= 0 && + (offs + numbytes <= headsize)) /* We have it in memory ? */ + { + for (k = 0; k < numbytes; k++) + fileval = (fileval << 8) | (glong) file_head[offs + k]; + } + else /* Read it from file */ + { + gint c = 0; + + if (fseek (ifp, offs, (offs >= 0) ? SEEK_SET : SEEK_END) < 0) + return FILE_MATCH_NONE; + + for (k = 0; k < numbytes; k++) + fileval = (fileval << 8) | (c = getc (ifp)); + + if (c == EOF) + return FILE_MATCH_NONE; + } + + if (num_operator == '&') + fileval &= num_operatorval; + + if (num_test == '<') + found = (fileval < num_testval); + else if (num_test == '>') + found = (fileval > num_testval); + else + found = (fileval == num_testval); + + if (found && (numbytes == 5)) + found = FILE_MATCH_SIZE; + } + else if (numbytes == 0) /* String test */ + { + gchar mem_testval[256]; + + file_convert_string (value, + mem_testval, sizeof (mem_testval), + &numbytes); + + if (numbytes <= 0) + return FILE_MATCH_NONE; + + if (offs >= 0 && + (offs + numbytes <= headsize)) /* We have it in memory ? */ + { + found = (memcmp (mem_testval, file_head + offs, numbytes) == 0); + } + else /* Read it from file */ + { + if (fseek (ifp, offs, (offs >= 0) ? SEEK_SET : SEEK_END) < 0) + return FILE_MATCH_NONE; + + found = FILE_MATCH_MAGIC; + + for (k = 0; found && (k < numbytes); k++) + { + gint c = getc (ifp); + + found = (c != EOF) && (c == (gint) mem_testval[k]); + } + } + } + + return found; +} + +static FileMatchType +file_check_magic_list (GSList *magics_list, + const guchar *head, + gint headsize, + FILE *ifp) + +{ + const gchar *offset; + const gchar *type; + const gchar *value; + gboolean and = FALSE; + gboolean found = FALSE; + FileMatchType match_val; + + while (magics_list) + { + if ((offset = magics_list->data) == NULL) break; + if ((magics_list = magics_list->next) == NULL) break; + if ((type = magics_list->data) == NULL) break; + if ((magics_list = magics_list->next) == NULL) break; + if ((value = magics_list->data) == NULL) break; + + magics_list = magics_list->next; + + match_val = file_check_single_magic (offset, type, value, + head, headsize, + ifp); + if (and) + found = found && (match_val != FILE_MATCH_NONE); + else + found = (match_val != FILE_MATCH_NONE); + + and = (strchr (offset, '&') != NULL); + + if (! and && found) + return match_val; + } + + return FILE_MATCH_NONE; +} diff --git a/app/file/file-procedure.h b/app/file/file-procedure.h new file mode 100644 index 0000000000..be4e205330 --- /dev/null +++ b/app/file/file-procedure.h @@ -0,0 +1,34 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * file-procedure.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __FILE_PROCEDURE_H__ +#define __FILE_PROCEDURE_H__ + + +GimpPlugInProcedure * file_procedure_find (GSList *procs, + const gchar *filename, + GError **error); +GimpPlugInProcedure * file_procedure_find_by_prefix (GSList *procs, + const gchar *uri); +GimpPlugInProcedure * file_procedure_find_by_extension (GSList *procs, + const gchar *uri); + + +#endif /* __FILE_PROCEDURE_H__ */ diff --git a/app/file/file-utils.c b/app/file/file-utils.c index f72b2f266c..2730f52f70 100644 --- a/app/file/file-utils.c +++ b/app/file/file-utils.c @@ -21,22 +21,9 @@ #include "config.h" -#include -#include #include -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - #include -#include #include @@ -51,56 +38,19 @@ #include "core/gimpimagefile.h" #include "plug-in/gimppluginmanager.h" -#include "plug-in/gimppluginprocedure.h" +#include "file-procedure.h" #include "file-utils.h" #include "gimp-intl.h" -typedef enum -{ - FILE_MATCH_NONE, - FILE_MATCH_MAGIC, - FILE_MATCH_SIZE -} FileMatchType; +static gchar * file_utils_unescape_uri (const gchar *escaped, + gint len, + const gchar *illegal_escaped_characters, + gboolean ascii_must_not_be_escaped); -/* local function prototypes */ - -static GimpPlugInProcedure * file_proc_find_by_prefix (GSList *procs, - const gchar *uri, - gboolean skip_magic); -static GimpPlugInProcedure * file_proc_find_by_extension (GSList *procs, - const gchar *uri, - gboolean skip_magic); -static GimpPlugInProcedure * file_proc_find_by_name (GSList *procs, - const gchar *uri, - gboolean skip_magic); - -static gchar * file_utils_unescape_uri (const gchar *escaped, - gint len, - const gchar *illegal_escaped_characters, - gboolean ascii_must_not_be_escaped); - -static void file_convert_string (const gchar *instr, - gchar *outmem, - gint maxmem, - gint *nmem); -static FileMatchType file_check_single_magic (const gchar *offset, - const gchar *type, - const gchar *value, - const guchar *file_head, - gint headsize, - FILE *ifp); -static FileMatchType file_check_magic_list (GSList *magics_list, - const guchar *head, - gint headsize, - FILE *ifp); - - -/* public functions */ - gchar * file_utils_filename_to_uri (Gimp *gimp, const gchar *filename, @@ -114,8 +64,8 @@ file_utils_filename_to_uri (Gimp *gimp, g_return_val_if_fail (error == NULL || *error == NULL, NULL); /* check for prefixes like http or ftp */ - if (file_proc_find_by_prefix (gimp->plug_in_manager->load_procs, - filename, FALSE)) + if (file_procedure_find_by_prefix (gimp->plug_in_manager->load_procs, + filename)) { if (g_utf8_validate (filename, -1, NULL)) { @@ -248,131 +198,6 @@ file_utils_filename_from_uri (const gchar *uri) return filename; } -GimpPlugInProcedure * -file_utils_find_proc (GSList *procs, - const gchar *uri, - GError **error) -{ - GimpPlugInProcedure *file_proc; - GSList *all_procs = procs; - gchar *filename; - - g_return_val_if_fail (procs != NULL, NULL); - g_return_val_if_fail (uri != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* First, check magicless prefixes/suffixes */ - file_proc = file_proc_find_by_name (all_procs, uri, TRUE); - - if (file_proc) - return file_proc; - - filename = file_utils_filename_from_uri (uri); - - /* Then look for magics */ - if (filename) - { - GimpPlugInProcedure *size_matched_proc = NULL; - FILE *ifp = NULL; - gint head_size = -2; - gint size_match_count = 0; - guchar head[256]; - - while (procs) - { - file_proc = procs->data; - procs = procs->next; - - if (file_proc->magics_list) - { - if (head_size == -2) - { - head_size = 0; - - if ((ifp = g_fopen (filename, "rb")) != NULL) - { - head_size = fread ((gchar *) head, 1, sizeof (head), ifp); - } - else - { - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - g_strerror (errno)); - } - } - - if (head_size >= 4) - { - FileMatchType match_val; - - match_val = file_check_magic_list (file_proc->magics_list, - head, head_size, - ifp); - - if (match_val == FILE_MATCH_SIZE) - { - /* Use it only if no other magic matches */ - size_match_count++; - size_matched_proc = file_proc; - } - else if (match_val != FILE_MATCH_NONE) - { - fclose (ifp); - g_free (filename); - - return file_proc; - } - } - } - } - - if (ifp) - { - if (ferror (ifp)) - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - g_strerror (errno)); - - fclose (ifp); - } - - g_free (filename); - - if (size_match_count == 1) - return size_matched_proc; - } - - /* As a last resort, try matching by name */ - file_proc = file_proc_find_by_name (all_procs, uri, FALSE); - - if (file_proc) - { - /* we found a procedure, clear error that might have been set */ - g_clear_error (error); - } - else - { - /* set an error message unless one was already set */ - if (error && *error == NULL) - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, - _("Unknown file type")); - } - - return file_proc; -} - -GimpPlugInProcedure * -file_utils_find_proc_by_extension (GSList *procs, - const gchar *uri) -{ - g_return_val_if_fail (procs != NULL, NULL); - g_return_val_if_fail (uri != NULL, NULL); - - return file_proc_find_by_extension (procs, uri, FALSE); -} - gchar * file_utils_uri_to_utf8_filename (const gchar *uri) { @@ -571,96 +396,6 @@ file_utils_save_thumbnail (GimpImage *image, } -/* private functions */ - -static GimpPlugInProcedure * -file_proc_find_by_prefix (GSList *procs, - const gchar *uri, - gboolean skip_magic) -{ - GSList *p; - - for (p = procs; p; p = g_slist_next (p)) - { - GimpPlugInProcedure *proc = p->data; - GSList *prefixes; - - if (skip_magic && proc->magics_list) - continue; - - for (prefixes = proc->prefixes_list; - prefixes; - prefixes = g_slist_next (prefixes)) - { - if (g_str_has_prefix (uri, prefixes->data)) - return proc; - } - } - - return NULL; -} - -static GimpPlugInProcedure * -file_proc_find_by_extension (GSList *procs, - const gchar *uri, - gboolean skip_magic) -{ - GSList *p; - const gchar *ext; - - ext = strrchr (uri, '.'); - - if (ext) - ext++; - - for (p = procs; p; p = g_slist_next (p)) - { - GimpPlugInProcedure *proc = p->data; - GSList *extensions; - - for (extensions = proc->extensions_list; - ext && extensions; - extensions = g_slist_next (extensions)) - { - const gchar *p1 = ext; - const gchar *p2 = extensions->data; - - if (skip_magic && proc->magics_list) - continue; - - while (*p1 && *p2) - { - if (g_ascii_tolower (*p1) != g_ascii_tolower (*p2)) - break; - - p1++; - p2++; - } - - if (!(*p1) && !(*p2)) - return proc; - } - } - - return NULL; -} - -static GimpPlugInProcedure * -file_proc_find_by_name (GSList *procs, - const gchar *uri, - gboolean skip_magic) -{ - GimpPlugInProcedure *proc; - - proc = file_proc_find_by_prefix (procs, uri, skip_magic); - - if (! proc) - proc = file_proc_find_by_extension (procs, uri, skip_magic); - - return proc; -} - - /* the following two functions are copied from glib/gconvert.c */ static gint @@ -740,265 +475,3 @@ file_utils_unescape_uri (const gchar *escaped, return result; } - -static void -file_convert_string (const gchar *instr, - gchar *outmem, - gint maxmem, - gint *nmem) -{ - /* Convert a string in C-notation to array of char */ - const guchar *uin = (const guchar *) instr; - guchar *uout = (guchar *) outmem; - guchar tmp[5], *tmpptr; - guint k; - - while ((*uin != '\0') && ((((gchar *) uout) - outmem) < maxmem)) - { - if (*uin != '\\') /* Not an escaped character ? */ - { - *(uout++) = *(uin++); - continue; - } - - if (*(++uin) == '\0') - { - *(uout++) = '\\'; - break; - } - - switch (*uin) - { - case '0': case '1': case '2': case '3': /* octal */ - for (tmpptr = tmp; (tmpptr - tmp) <= 3;) - { - *(tmpptr++) = *(uin++); - if ( (*uin == '\0') || (!g_ascii_isdigit (*uin)) - || (*uin == '8') || (*uin == '9')) - break; - } - - *tmpptr = '\0'; - sscanf ((gchar *) tmp, "%o", &k); - *(uout++) = k; - break; - - case 'a': *(uout++) = '\a'; uin++; break; - case 'b': *(uout++) = '\b'; uin++; break; - case 't': *(uout++) = '\t'; uin++; break; - case 'n': *(uout++) = '\n'; uin++; break; - case 'v': *(uout++) = '\v'; uin++; break; - case 'f': *(uout++) = '\f'; uin++; break; - case 'r': *(uout++) = '\r'; uin++; break; - - default : *(uout++) = *(uin++); break; - } - } - - *nmem = ((gchar *) uout) - outmem; -} - -static FileMatchType -file_check_single_magic (const gchar *offset, - const gchar *type, - const gchar *value, - const guchar *file_head, - gint headsize, - FILE *ifp) - -{ - FileMatchType found = FILE_MATCH_NONE; - glong offs; - gulong num_testval; - gulong num_operatorval; - gint numbytes, k; - const gchar *num_operator_ptr; - gchar num_operator; - - /* Check offset */ - if (sscanf (offset, "%ld", &offs) != 1) - return FILE_MATCH_NONE; - - /* Check type of test */ - num_operator_ptr = NULL; - num_operator = '\0'; - - if (g_str_has_prefix (type, "byte")) - { - numbytes = 1; - num_operator_ptr = type + strlen ("byte"); - } - else if (g_str_has_prefix (type, "short")) - { - numbytes = 2; - num_operator_ptr = type + strlen ("short"); - } - else if (g_str_has_prefix (type, "long")) - { - numbytes = 4; - num_operator_ptr = type + strlen ("long"); - } - else if (g_str_has_prefix (type, "size")) - { - numbytes = 5; - } - else if (strcmp (type, "string") == 0) - { - numbytes = 0; - } - else - { - return FILE_MATCH_NONE; - } - - /* Check numerical operator value if present */ - if (num_operator_ptr && (*num_operator_ptr == '&')) - { - if (g_ascii_isdigit (num_operator_ptr[1])) - { - if (num_operator_ptr[1] != '0') /* decimal */ - sscanf (num_operator_ptr+1, "%lu", &num_operatorval); - else if (num_operator_ptr[2] == 'x') /* hexadecimal */ - sscanf (num_operator_ptr+3, "%lx", &num_operatorval); - else /* octal */ - sscanf (num_operator_ptr+2, "%lo", &num_operatorval); - - num_operator = *num_operator_ptr; - } - } - - if (numbytes > 0) /* Numerical test ? */ - { - gchar num_test = '='; - gulong fileval = 0; - - /* Check test value */ - if ((value[0] == '>') || (value[0] == '<')) - { - num_test = value[0]; - value++; - } - - errno = 0; - num_testval = strtol (value, NULL, 0); - - if (errno != 0) - return FILE_MATCH_NONE; - - if (numbytes == 5) /* Check for file size ? */ - { - struct stat buf; - - if (fstat (fileno (ifp), &buf) < 0) - return FILE_MATCH_NONE; - - fileval = buf.st_size; - } - else if (offs >= 0 && - (offs + numbytes <= headsize)) /* We have it in memory ? */ - { - for (k = 0; k < numbytes; k++) - fileval = (fileval << 8) | (glong) file_head[offs + k]; - } - else /* Read it from file */ - { - gint c = 0; - - if (fseek (ifp, offs, (offs >= 0) ? SEEK_SET : SEEK_END) < 0) - return FILE_MATCH_NONE; - - for (k = 0; k < numbytes; k++) - fileval = (fileval << 8) | (c = getc (ifp)); - - if (c == EOF) - return FILE_MATCH_NONE; - } - - if (num_operator == '&') - fileval &= num_operatorval; - - if (num_test == '<') - found = (fileval < num_testval); - else if (num_test == '>') - found = (fileval > num_testval); - else - found = (fileval == num_testval); - - if (found && (numbytes == 5)) - found = FILE_MATCH_SIZE; - } - else if (numbytes == 0) /* String test */ - { - gchar mem_testval[256]; - - file_convert_string (value, - mem_testval, sizeof (mem_testval), - &numbytes); - - if (numbytes <= 0) - return FILE_MATCH_NONE; - - if (offs >= 0 && - (offs + numbytes <= headsize)) /* We have it in memory ? */ - { - found = (memcmp (mem_testval, file_head + offs, numbytes) == 0); - } - else /* Read it from file */ - { - if (fseek (ifp, offs, (offs >= 0) ? SEEK_SET : SEEK_END) < 0) - return FILE_MATCH_NONE; - - found = FILE_MATCH_MAGIC; - - for (k = 0; found && (k < numbytes); k++) - { - gint c = getc (ifp); - - found = (c != EOF) && (c == (gint) mem_testval[k]); - } - } - } - - return found; -} - -static FileMatchType -file_check_magic_list (GSList *magics_list, - const guchar *head, - gint headsize, - FILE *ifp) - -{ - const gchar *offset; - const gchar *type; - const gchar *value; - gboolean and = FALSE; - gboolean found = FALSE; - FileMatchType match_val; - - while (magics_list) - { - if ((offset = magics_list->data) == NULL) break; - if ((magics_list = magics_list->next) == NULL) break; - if ((type = magics_list->data) == NULL) break; - if ((magics_list = magics_list->next) == NULL) break; - if ((value = magics_list->data) == NULL) break; - - magics_list = magics_list->next; - - match_val = file_check_single_magic (offset, type, value, - head, headsize, - ifp); - if (and) - found = found && (match_val != FILE_MATCH_NONE); - else - found = (match_val != FILE_MATCH_NONE); - - and = (strchr (offset, '&') != NULL); - - if (! and && found) - return match_val; - } - - return FILE_MATCH_NONE; -} diff --git a/app/file/file-utils.h b/app/file/file-utils.h index cfad8b385f..b8bf7600f1 100644 --- a/app/file/file-utils.h +++ b/app/file/file-utils.h @@ -25,28 +25,22 @@ #include -gchar * file_utils_filename_to_uri (Gimp *gimp, - const gchar *filename, - GError **error); -gchar * file_utils_any_to_uri (Gimp *gimp, - const gchar *filename_or_uri, - GError **error); -gchar * file_utils_filename_from_uri (const gchar *uri); +gchar * file_utils_filename_to_uri (Gimp *gimp, + const gchar *filename, + GError **error); +gchar * file_utils_any_to_uri (Gimp *gimp, + const gchar *filename_or_uri, + GError **error); +gchar * file_utils_filename_from_uri (const gchar *uri); -gchar * file_utils_uri_to_utf8_filename (const gchar *uri); +gchar * file_utils_uri_to_utf8_filename (const gchar *uri); -gchar * file_utils_uri_display_basename (const gchar *uri); -gchar * file_utils_uri_display_name (const gchar *uri); +gchar * file_utils_uri_display_basename (const gchar *uri); +gchar * file_utils_uri_display_name (const gchar *uri); -GimpPlugInProcedure * file_utils_find_proc (GSList *procs, - const gchar *filename, - GError **error); -GimpPlugInProcedure * file_utils_find_proc_by_extension (GSList *procs, - const gchar *uri); - -GdkPixbuf * file_utils_load_thumbnail (const gchar *filename); -gboolean file_utils_save_thumbnail (GimpImage *image, - const gchar *filename); +GdkPixbuf * file_utils_load_thumbnail (const gchar *filename); +gboolean file_utils_save_thumbnail (GimpImage *image, + const gchar *filename); #endif /* __FILE_UTILS_H__ */ diff --git a/app/pdb/fileops_cmds.c b/app/pdb/fileops_cmds.c index a3b4e3c4dc..5097af5293 100644 --- a/app/pdb/fileops_cmds.c +++ b/app/pdb/fileops_cmds.c @@ -37,6 +37,7 @@ #include "core/gimpimage.h" #include "core/gimplayer.h" #include "file/file-open.h" +#include "file/file-procedure.h" #include "file/file-save.h" #include "file/file-utils.h" #include "plug-in/gimppluginmanager-file.h" @@ -67,7 +68,7 @@ file_load_invoker (GimpProcedure *procedure, return gimp_procedure_get_return_values (procedure, FALSE); file_proc = - file_utils_find_proc (gimp->plug_in_manager->load_procs, uri, NULL); + file_procedure_find (gimp->plug_in_manager->load_procs, uri, NULL); g_free (uri); @@ -235,7 +236,7 @@ file_save_invoker (GimpProcedure *procedure, return gimp_procedure_get_return_values (procedure, FALSE); file_proc = - file_utils_find_proc (gimp->plug_in_manager->save_procs, uri, NULL); + file_procedure_find (gimp->plug_in_manager->save_procs, uri, NULL); g_free (uri); diff --git a/app/widgets/gimpdnd-xds.c b/app/widgets/gimpdnd-xds.c index 62e89592b9..bac470267c 100644 --- a/app/widgets/gimpdnd-xds.c +++ b/app/widgets/gimpdnd-xds.c @@ -40,6 +40,7 @@ #include "plug-in/gimppluginmanager.h" +#include "file/file-procedure.h" #include "file/file-save.h" #include "file/file-utils.h" @@ -144,8 +145,8 @@ gimp_dnd_xds_save_image (GdkDragContext *context, uri = g_strndup ((const gchar *) data, length); g_free (data); - proc = - file_utils_find_proc (image->gimp->plug_in_manager->save_procs, uri, NULL); + proc = file_procedure_find (image->gimp->plug_in_manager->save_procs, uri, + NULL); if (proc) { diff --git a/app/widgets/gimpimagepropview.c b/app/widgets/gimpimagepropview.c index f2ee8178af..58315d13e2 100644 --- a/app/widgets/gimpimagepropview.c +++ b/app/widgets/gimpimagepropview.c @@ -43,6 +43,7 @@ #include "core/gimpunit.h" #include "core/gimp-utils.h" +#include "file/file-procedure.h" #include "file/file-utils.h" #include "plug-in/gimppluginmanager.h" @@ -371,7 +372,7 @@ gimp_image_prop_view_label_set_filetype (GtkWidget *label, if (filename) { - proc = file_utils_find_proc (manager->load_procs, filename, NULL); + proc = file_procedure_find (manager->load_procs, filename, NULL); g_free (filename); } } diff --git a/app/widgets/gimpthumbbox.c b/app/widgets/gimpthumbbox.c index 9274556424..8f3e0b3be5 100644 --- a/app/widgets/gimpthumbbox.c +++ b/app/widgets/gimpthumbbox.c @@ -37,6 +37,7 @@ #include "plug-in/gimppluginmanager.h" +#include "file/file-procedure.h" #include "file/file-utils.h" #include "gimpfiledialog.h" /* eek */ @@ -718,8 +719,8 @@ gimp_thumb_box_auto_thumbnail (GimpThumbBox *box) case GIMP_THUMB_STATE_OLD: if (thumb->image_filesize < gimp->config->thumbnail_filesize_limit && ! gimp_thumbnail_has_failed (thumb) && - file_utils_find_proc_by_extension (gimp->plug_in_manager->load_procs, - uri)) + file_procedure_find_by_extension (gimp->plug_in_manager->load_procs, + uri)) { if (thumb->image_filesize > 0) { diff --git a/tools/pdbgen/pdb/fileops.pdb b/tools/pdbgen/pdb/fileops.pdb index f08c8c7d40..36ec27591e 100644 --- a/tools/pdbgen/pdb/fileops.pdb +++ b/tools/pdbgen/pdb/fileops.pdb @@ -66,7 +66,7 @@ HELP return gimp_procedure_get_return_values (procedure, FALSE); file_proc = - file_utils_find_proc (gimp->plug_in_manager->load_procs, uri, NULL); + file_procedure_find (gimp->plug_in_manager->load_procs, uri, NULL); g_free (uri); @@ -268,7 +268,7 @@ HELP return gimp_procedure_get_return_values (procedure, FALSE); file_proc = - file_utils_find_proc (gimp->plug_in_manager->save_procs, uri, NULL); + file_procedure_find (gimp->plug_in_manager->save_procs, uri, NULL); g_free (uri); @@ -597,6 +597,7 @@ CODE "plug-in/gimppluginmanager-file.h" "file/file-open.h" "file/file-save.h" + "file/file-procedure.h" "file/file-utils.h"); @procs = qw(file_load file_load_layer file_load_layers