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 (GSList *procs, const gchar *uri, GError **error) { GimpPlugInProcedure *file_proc; 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: */ if (! file_proc_find_by_extension (procs, uri, FALSE, TRUE)) { /* If there is not any (with or without magic) file proc that * can load the URI by extension directly, try to find a proc * that can load the prefix */ file_proc = file_proc_find_by_prefix (procs, uri, TRUE); } else { /* Otherwise try to find a magicless file proc that handles the * extension */ file_proc = file_proc_find_by_extension (procs, uri, TRUE, FALSE); } if (file_proc) return file_proc; filename = file_utils_filename_from_uri (uri); /* Then look for magics */ if (filename) { GSList *list; GimpPlugInProcedure *size_matched_proc = NULL; FILE *ifp = NULL; gboolean opened = FALSE; gint head_size = 0; gint size_match_count = 0; guchar head[256]; for (list = procs; list; list = g_slist_next (list)) { file_proc = procs->data; if (file_proc->magics_list) { if (G_UNLIKELY (!opened)) { ifp = g_fopen (filename, "rb"); if (ifp != NULL) head_size = fread ((gchar *) head, 1, sizeof (head), ifp); else g_set_error_literal (error, G_FILE_ERROR, g_file_error_from_errno (errno), g_strerror (errno)); opened = TRUE; } 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_literal (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, not skipping magic procs */ file_proc = file_proc_find_by_name (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_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Unknown file type")); } return file_proc; }