22
22
#include "config.h"
25
25
#include <stdlib.h>
26
26
#include <string.h>
27
28
#ifdef HAVE_SYS_PARAM_H
28
29
#include <sys/param.h>
30
32
#include <sys/types.h>
32
34
#ifdef HAVE_UNISTD_H
33
35
#include <unistd.h>
36
38
#include <glib-object.h>
39
#include <glib/gstdio.h>
41
#include <gdk-pixbuf/gdk-pixbuf.h>
43
#include "libgimpbase/gimpbase.h"
38
44
#include "libgimpmath/gimpmath.h"
45
#include "libgimpthumb/gimpthumb.h"
40
47
#include "core/core-types.h"
42
#include "base/temp-buf.h"
44
49
#include "core/gimp.h"
45
50
#include "core/gimpimage.h"
47
#include "pdb/procedural_db.h"
49
#include "plug-in/plug-in.h"
50
#include "plug-in/plug-in-proc-def.h"
51
#include "core/gimpimagefile.h"
53
#include "plug-in/gimppluginmanager.h"
54
#include "plug-in/gimppluginprocedure.h"
52
56
#include "file-utils.h"
54
58
#include "gimp-intl.h"
57
69
/* local function prototypes */
59
static PlugInProcDef * file_proc_find_by_prefix (GSList *procs,
62
static PlugInProcDef * file_proc_find_by_extension (GSList *procs,
65
static PlugInProcDef * file_proc_find_by_name (GSList *procs,
68
static void file_convert_string (const gchar *instr,
72
static gint file_check_single_magic (const gchar *offset,
75
const guchar *file_head,
78
static gint file_check_magic_list (GSList *magics_list,
71
static GimpPlugInProcedure * file_proc_find_by_prefix (GSList *procs,
74
static GimpPlugInProcedure * file_proc_find_by_extension (GSList *procs,
77
static GimpPlugInProcedure * file_proc_find_by_name (GSList *procs,
81
static gchar * file_utils_unescape_uri (const gchar *escaped,
83
const gchar *illegal_escaped_characters,
84
gboolean ascii_must_not_be_escaped);
86
static void file_convert_string (const gchar *instr,
90
static FileMatchType file_check_single_magic (const gchar *offset,
93
const guchar *file_head,
96
static FileMatchType file_check_magic_list (GSList *magics_list,
84
102
/* public functions */
87
file_utils_filename_to_uri (GSList *procs,
105
file_utils_filename_to_uri (Gimp *gimp,
88
106
const gchar *filename,
94
g_return_val_if_fail (procs != NULL, NULL);
112
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
95
113
g_return_val_if_fail (filename != NULL, NULL);
114
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
97
116
/* check for prefixes like http or ftp */
98
if (file_proc_find_by_prefix (procs, filename, FALSE))
117
if (file_proc_find_by_prefix (gimp->plug_in_manager->load_procs,
100
120
if (g_utf8_validate (filename, -1, NULL))
131
else if (strstr (filename, "://"))
136
scheme = g_strndup (filename, (strstr (filename, "://") - filename));
137
canon = g_strdup (scheme);
139
g_strcanon (canon, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "+-.", '-');
141
if (! strcmp (scheme, canon) && g_ascii_isgraph (canon[0]))
143
g_set_error (error, G_FILE_ERROR, 0,
144
_("URI scheme '%s:' is not supported"), scheme);
112
156
if (! g_path_is_absolute (filename))
177
file_utils_any_to_uri (Gimp *gimp,
178
const gchar *filename_or_uri,
183
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
184
g_return_val_if_fail (filename_or_uri != NULL, NULL);
185
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
187
/* first try if we got a file uri */
188
uri = g_filename_from_uri (filename_or_uri, NULL, NULL);
193
uri = g_strdup (filename_or_uri);
197
uri = file_utils_filename_to_uri (gimp, filename_or_uri, error);
133
205
* file_utils_filename_from_uri:
251
GimpPlugInProcedure *
180
252
file_utils_find_proc (GSList *procs,
183
PlugInProcDef *file_proc;
184
GSList *all_procs = procs;
256
GimpPlugInProcedure *file_proc;
257
GSList *all_procs = procs;
187
260
g_return_val_if_fail (procs != NULL, NULL);
188
261
g_return_val_if_fail (uri != NULL, NULL);
262
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
190
264
/* First, check magicless prefixes/suffixes */
191
265
file_proc = file_proc_find_by_name (all_procs, uri, TRUE);
215
288
if (head_size == -2)
218
if ((ifp = fopen (filename, "rb")) != NULL)
219
head_size = fread ((gchar *) head, 1, sizeof (head), ifp);
292
if ((ifp = g_fopen (filename, "rb")) != NULL)
294
head_size = fread ((gchar *) head, 1, sizeof (head), ifp);
300
g_file_error_from_errno (errno),
222
305
if (head_size >= 4)
307
FileMatchType match_val;
224
309
match_val = file_check_magic_list (file_proc->magics_list,
228
if (match_val == 2) /* size match ? */
229
{ /* Use it only if no other magic matches */
313
if (match_val == FILE_MATCH_SIZE)
315
/* Use it only if no other magic matches */
230
316
size_match_count++;
231
317
size_matched_proc = file_proc;
319
else if (match_val != FILE_MATCH_NONE)
236
322
g_free (filename);
253
347
/* As a last resort, try matching by name */
254
return file_proc_find_by_name (all_procs, uri, FALSE);
348
file_proc = file_proc_find_by_name (all_procs, uri, FALSE);
352
/* we found a procedure, clear error that might have been set */
353
g_clear_error (error);
357
/* set an error message unless one was already set */
358
if (error && *error == NULL)
359
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
360
_("Unknown file type"));
366
GimpPlugInProcedure *
258
367
file_utils_find_proc_by_extension (GSList *procs,
259
368
const gchar *uri)
268
file_utils_uri_to_utf8_basename (const gchar *uri)
273
g_return_val_if_fail (uri != NULL, NULL);
275
filename = file_utils_uri_to_utf8_filename (uri);
277
if (strstr (filename, G_DIR_SEPARATOR_S))
279
basename = g_path_get_basename (filename);
285
else if (strstr (filename, "://"))
287
basename = strrchr (uri, '/');
289
basename = g_strdup (basename + 1);
300
377
file_utils_uri_to_utf8_filename (const gchar *uri)
302
379
g_return_val_if_fail (uri != NULL, NULL);
325
402
return g_strdup (uri);
406
file_utils_uri_to_utf8_basename (const gchar *uri)
409
gchar *basename = NULL;
411
g_return_val_if_fail (uri != NULL, NULL);
413
filename = file_utils_uri_to_utf8_filename (uri);
415
if (strstr (filename, G_DIR_SEPARATOR_S))
417
basename = g_path_get_basename (filename);
419
else if (strstr (filename, "://"))
421
basename = strrchr (uri, '/');
424
basename = g_strdup (basename + 1);
437
file_utils_uri_display_basename (const gchar *uri)
439
gchar *basename = NULL;
441
g_return_val_if_fail (uri != NULL, NULL);
443
if (g_str_has_prefix (uri, "file:"))
445
gchar *filename = file_utils_filename_from_uri (uri);
449
basename = g_filename_display_basename (filename);
455
gchar *name = file_utils_uri_display_name (uri);
457
basename = strrchr (name, '/');
459
basename = g_strdup (basename + 1);
464
return basename ? basename : file_utils_uri_to_utf8_basename (uri);
468
file_utils_uri_display_name (const gchar *uri)
472
g_return_val_if_fail (uri != NULL, NULL);
474
if (g_str_has_prefix (uri, "file:"))
476
gchar *filename = file_utils_filename_from_uri (uri);
480
name = g_filename_display_name (filename);
486
name = file_utils_unescape_uri (uri, -1, "/", FALSE);
489
return name ? name : g_strdup (uri);
493
file_utils_load_thumbnail (const gchar *filename)
495
GimpThumbnail *thumbnail = NULL;
496
GdkPixbuf *pixbuf = NULL;
499
g_return_val_if_fail (filename != NULL, NULL);
501
uri = g_filename_to_uri (filename, NULL, NULL);
505
thumbnail = gimp_thumbnail_new ();
506
gimp_thumbnail_set_uri (thumbnail, uri);
508
pixbuf = gimp_thumbnail_load_thumb (thumbnail,
509
GIMP_THUMBNAIL_SIZE_NORMAL,
517
gint width = gdk_pixbuf_get_width (pixbuf);
518
gint height = gdk_pixbuf_get_height (pixbuf);
520
if (gdk_pixbuf_get_n_channels (pixbuf) != 3)
522
GdkPixbuf *tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
525
gdk_pixbuf_composite_color (pixbuf, tmp,
526
0, 0, width, height, 0, 0, 1.0, 1.0,
527
GDK_INTERP_NEAREST, 255,
528
0, 0, GIMP_CHECK_SIZE_SM,
529
0x66666666, 0x99999999);
531
g_object_unref (pixbuf);
540
file_utils_save_thumbnail (GimpImage *image,
541
const gchar *filename)
543
const gchar *image_uri;
544
gboolean success = FALSE;
546
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
547
g_return_val_if_fail (filename != NULL, FALSE);
549
image_uri = gimp_object_get_name (GIMP_OBJECT (image));
553
gchar *uri = g_filename_to_uri (filename, NULL, NULL);
557
if ( ! strcmp (uri, image_uri))
559
GimpImagefile *imagefile;
561
imagefile = gimp_imagefile_new (image->gimp, uri);
562
success = gimp_imagefile_save_thumbnail (imagefile, NULL, image);
563
g_object_unref (imagefile);
329
574
/* private functions */
331
static PlugInProcDef *
576
static GimpPlugInProcedure *
332
577
file_proc_find_by_prefix (GSList *procs,
333
578
const gchar *uri,
334
579
gboolean skip_magic)
338
583
for (p = procs; p; p = g_slist_next (p))
340
PlugInProcDef *proc = p->data;
585
GimpPlugInProcedure *proc = p->data;
343
588
if (skip_magic && proc->magics_list)
346
591
for (prefixes = proc->prefixes_list;
348
prefixes = g_slist_next (prefixes))
350
if (strncmp (uri, prefixes->data, strlen (prefixes->data)) == 0)
593
prefixes = g_slist_next (prefixes))
595
if (g_str_has_prefix (uri, prefixes->data))
358
static PlugInProcDef *
603
static GimpPlugInProcedure *
359
604
file_proc_find_by_extension (GSList *procs,
360
605
const gchar *uri,
361
606
gboolean skip_magic)
371
616
for (p = procs; p; p = g_slist_next (p))
373
PlugInProcDef *proc = p->data;
618
GimpPlugInProcedure *proc = p->data;
376
621
for (extensions = proc->extensions_list;
378
extensions = g_slist_next (extensions))
380
const gchar *p1 = ext;
381
const gchar *p2 = extensions->data;
623
extensions = g_slist_next (extensions))
625
const gchar *p1 = ext;
626
const gchar *p2 = extensions->data;
383
628
if (skip_magic && proc->magics_list)
388
if (g_ascii_tolower (*p1) != g_ascii_tolower (*p2))
395
if (!(*p1) && !(*p2))
633
if (g_ascii_tolower (*p1) != g_ascii_tolower (*p2))
640
if (!(*p1) && !(*p2))
403
static PlugInProcDef *
648
static GimpPlugInProcedure *
404
649
file_proc_find_by_name (GSList *procs,
653
GimpPlugInProcedure *proc;
410
655
proc = file_proc_find_by_prefix (procs, uri, skip_magic);
664
/* the following two functions are copied from glib/gconvert.c */
667
unescape_character (const gchar *scanner)
672
first_digit = g_ascii_xdigit_value (scanner[0]);
676
second_digit = g_ascii_xdigit_value (scanner[1]);
677
if (second_digit < 0)
680
return (first_digit << 4) | second_digit;
684
file_utils_unescape_uri (const gchar *escaped,
686
const gchar *illegal_escaped_characters,
687
gboolean ascii_must_not_be_escaped)
689
const gchar *in, *in_end;
697
len = strlen (escaped);
699
result = g_malloc (len + 1);
702
for (in = escaped, in_end = escaped + len; in < in_end; in++)
708
/* catch partial escape sequences past the end of the substring */
712
c = unescape_character (in + 1);
714
/* catch bad escape sequences and NUL characters */
718
/* catch escaped ASCII */
719
if (ascii_must_not_be_escaped && c <= 0x7F)
722
/* catch other illegal escaped characters */
723
if (strchr (illegal_escaped_characters, c) != NULL)
732
g_assert (out - result <= len);
419
745
file_convert_string (const gchar *instr,
424
750
/* Convert a string in C-notation to array of char */
425
751
const guchar *uin = (const guchar *) instr;
484
/* Return values are 0: no match, 1: magic match, 2: size match */
810
FileMatchType found = FILE_MATCH_NONE;
486
gulong num_testval, num_operatorval;
813
gulong num_operatorval;
488
814
gint numbytes, k;
491
815
const gchar *num_operator_ptr;
492
816
gchar num_operator;
494
guchar mem_testval[256];
496
818
/* Check offset */
497
if (sscanf (offset, "%ld", &offs) != 1) return (0);
498
if (offs < 0) return (0);
819
if (sscanf (offset, "%ld", &offs) != 1)
820
return FILE_MATCH_NONE;
500
822
/* Check type of test */
501
823
num_operator_ptr = NULL;
502
824
num_operator = '\0';
505
if (strncmp (type, "byte", 4) == 0)
826
if (g_str_has_prefix (type, "byte"))
508
num_operator_ptr = type + 4;
829
num_operator_ptr = type + strlen ("byte");
510
else if (strncmp (type, "short", 5) == 0)
831
else if (g_str_has_prefix (type, "short"))
513
num_operator_ptr = type + 5;
834
num_operator_ptr = type + strlen ("short");
515
else if (strncmp (type, "long", 4) == 0)
836
else if (g_str_has_prefix (type, "long"))
518
num_operator_ptr = type + 4;
839
num_operator_ptr = type + strlen ("long");
520
else if (strncmp (type, "size", 4) == 0)
841
else if (g_str_has_prefix (type, "size"))
538
862
sscanf (num_operator_ptr+3, "%lx", &num_operatorval);
540
864
sscanf (num_operator_ptr+2, "%lo", &num_operatorval);
541
866
num_operator = *num_operator_ptr;
545
870
if (numbytes > 0) /* Numerical test ? */
872
gchar num_test = '=';
547
875
/* Check test value */
548
if ((value[0] == '=') || (value[0] == '>') || (value[0] == '<'))
553
if (!g_ascii_isdigit (value[0])) return (0);
556
* to anybody reading this: is strtol's parsing behaviour
557
* (e.g. "0x" prefix) broken on some systems or why do we
558
* do the base detection ourselves?
560
if (value[0] != '0') /* decimal */
561
num_testval = strtol(value, NULL, 10);
562
else if (value[1] == 'x') /* hexadecimal */
563
num_testval = (unsigned long)strtoul(value+2, NULL, 16);
565
num_testval = strtol(value+1, NULL, 8);
876
if ((value[0] == '>') || (value[0] == '<'))
883
num_testval = strtol (value, NULL, 0);
886
return FILE_MATCH_NONE;
568
888
if (numbytes == 5) /* Check for file size ? */
572
if (fstat (fileno (ifp), &buf) < 0) return (0);
892
if (fstat (fileno (ifp), &buf) < 0)
893
return FILE_MATCH_NONE;
573
895
fileval = buf.st_size;
575
else if (offs + numbytes <= headsize) /* We have it in memory ? */
897
else if (offs >= 0 &&
898
(offs + numbytes <= headsize)) /* We have it in memory ? */
577
900
for (k = 0; k < numbytes; k++)
578
fileval = (fileval << 8) | (long)file_head[offs+k];
901
fileval = (fileval << 8) | (glong) file_head[offs + k];
580
903
else /* Read it from file */
582
if (fseek (ifp, offs, SEEK_SET) < 0) return (0);
907
if (fseek (ifp, offs, (offs >= 0) ? SEEK_SET : SEEK_END) < 0)
908
return FILE_MATCH_NONE;
583
910
for (k = 0; k < numbytes; k++)
584
911
fileval = (fileval << 8) | (c = getc (ifp));
585
if (c == EOF) return (0);
914
return FILE_MATCH_NONE;
587
917
if (num_operator == '&')
588
918
fileval &= num_operatorval;
595
925
found = (fileval == num_testval);
597
if (found && (numbytes == 5)) found = 2;
927
if (found && (numbytes == 5))
928
found = FILE_MATCH_SIZE;
599
930
else if (numbytes == 0) /* String test */
932
gchar mem_testval[256];
601
934
file_convert_string (value,
602
935
mem_testval, sizeof (mem_testval),
605
if (numbytes <= 0) return (0);
939
return FILE_MATCH_NONE;
607
if (offs + numbytes <= headsize) /* We have it in memory ? */
942
(offs + numbytes <= headsize)) /* We have it in memory ? */
609
found = (memcmp (mem_testval, file_head+offs, numbytes) == 0);
944
found = (memcmp (mem_testval, file_head + offs, numbytes) == 0);
611
946
else /* Read it from file */
613
if (fseek (ifp, offs, SEEK_SET) < 0) return (0);
948
if (fseek (ifp, offs, (offs >= 0) ? SEEK_SET : SEEK_END) < 0)
949
return FILE_MATCH_NONE;
951
found = FILE_MATCH_MAGIC;
615
953
for (k = 0; found && (k < numbytes); k++)
618
found = (c != EOF) && (c == (int)mem_testval[k]);
957
found = (c != EOF) && (c == (gint) mem_testval[k]);