~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to app/file/file-utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* The GIMP -- an image manipulation program
 
1
/* GIMP - The GNU Image Manipulation Program
2
2
 * Copyright (C) 1995, 1996, 1997 Spencer Kimball and Peter Mattis
3
3
 * Copyright (C) 1997 Josh MacDonald
4
4
 *
21
21
 
22
22
#include "config.h"
23
23
 
24
 
#include <stdio.h>
 
24
#include <errno.h>
25
25
#include <stdlib.h>
26
26
#include <string.h>
 
27
 
27
28
#ifdef HAVE_SYS_PARAM_H
28
29
#include <sys/param.h>
29
30
#endif
 
31
 
30
32
#include <sys/types.h>
31
 
#include <sys/stat.h>
 
33
 
32
34
#ifdef HAVE_UNISTD_H
33
35
#include <unistd.h>
34
36
#endif
35
37
 
36
38
#include <glib-object.h>
37
 
 
 
39
#include <glib/gstdio.h>
 
40
 
 
41
#include <gdk-pixbuf/gdk-pixbuf.h>
 
42
 
 
43
#include "libgimpbase/gimpbase.h"
38
44
#include "libgimpmath/gimpmath.h"
 
45
#include "libgimpthumb/gimpthumb.h"
39
46
 
40
47
#include "core/core-types.h"
41
48
 
42
 
#include "base/temp-buf.h"
43
 
 
44
49
#include "core/gimp.h"
45
50
#include "core/gimpimage.h"
46
 
 
47
 
#include "pdb/procedural_db.h"
48
 
 
49
 
#include "plug-in/plug-in.h"
50
 
#include "plug-in/plug-in-proc-def.h"
 
51
#include "core/gimpimagefile.h"
 
52
 
 
53
#include "plug-in/gimppluginmanager.h"
 
54
#include "plug-in/gimppluginprocedure.h"
51
55
 
52
56
#include "file-utils.h"
53
57
 
54
58
#include "gimp-intl.h"
55
59
 
56
60
 
 
61
typedef enum
 
62
{
 
63
  FILE_MATCH_NONE,
 
64
  FILE_MATCH_MAGIC,
 
65
  FILE_MATCH_SIZE
 
66
} FileMatchType;
 
67
 
 
68
 
57
69
/*  local function prototypes  */
58
70
 
59
 
static PlugInProcDef * file_proc_find_by_prefix    (GSList       *procs,
60
 
                                                    const gchar  *uri,
61
 
                                                    gboolean      skip_magic);
62
 
static PlugInProcDef * file_proc_find_by_extension (GSList       *procs,
63
 
                                                    const gchar  *uri,
64
 
                                                    gboolean      skip_magic);
65
 
static PlugInProcDef * file_proc_find_by_name      (GSList       *procs,
66
 
                                                    const gchar  *uri,
67
 
                                                    gboolean      skip_magic);
68
 
static void            file_convert_string         (const gchar  *instr,
69
 
                                                    gchar        *outmem,
70
 
                                                    gint          maxmem,
71
 
                                                    gint         *nmem);
72
 
static gint            file_check_single_magic     (const gchar  *offset,
73
 
                                                    const gchar  *type,
74
 
                                                    const gchar  *value,
75
 
                                                    const guchar *file_head,
76
 
                                                    gint          headsize,
77
 
                                                    FILE         *ifp);
78
 
static gint            file_check_magic_list       (GSList       *magics_list,
79
 
                                                    const guchar *head,
80
 
                                                    gint          headsize,
81
 
                                                    FILE         *ifp);
 
71
static GimpPlugInProcedure * file_proc_find_by_prefix    (GSList       *procs,
 
72
                                                          const gchar  *uri,
 
73
                                                          gboolean      skip_magic);
 
74
static GimpPlugInProcedure * file_proc_find_by_extension (GSList       *procs,
 
75
                                                          const gchar  *uri,
 
76
                                                          gboolean      skip_magic);
 
77
static GimpPlugInProcedure * file_proc_find_by_name      (GSList       *procs,
 
78
                                                          const gchar  *uri,
 
79
                                                          gboolean      skip_magic);
 
80
 
 
81
static gchar *               file_utils_unescape_uri     (const gchar  *escaped,
 
82
                                                          gint          len,
 
83
                                                          const gchar  *illegal_escaped_characters,
 
84
                                                          gboolean      ascii_must_not_be_escaped);
 
85
 
 
86
static void                  file_convert_string         (const gchar  *instr,
 
87
                                                          gchar        *outmem,
 
88
                                                          gint          maxmem,
 
89
                                                          gint         *nmem);
 
90
static FileMatchType         file_check_single_magic     (const gchar  *offset,
 
91
                                                          const gchar  *type,
 
92
                                                          const gchar  *value,
 
93
                                                          const guchar *file_head,
 
94
                                                          gint          headsize,
 
95
                                                          FILE         *ifp);
 
96
static FileMatchType         file_check_magic_list       (GSList       *magics_list,
 
97
                                                          const guchar *head,
 
98
                                                          gint          headsize,
 
99
                                                          FILE         *ifp);
82
100
 
83
101
 
84
102
/*  public functions  */
85
103
 
86
104
gchar *
87
 
file_utils_filename_to_uri (GSList       *procs,
 
105
file_utils_filename_to_uri (Gimp         *gimp,
88
106
                            const gchar  *filename,
89
107
                            GError      **error)
90
108
{
91
109
  gchar *absolute;
92
110
  gchar *uri;
93
111
 
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);
96
115
 
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,
 
118
                                filename, FALSE))
99
119
    {
100
120
      if (g_utf8_validate (filename, -1, NULL))
101
121
        {
108
128
          return NULL;
109
129
        }
110
130
    }
 
131
  else if (strstr (filename, "://"))
 
132
    {
 
133
      gchar *scheme;
 
134
      gchar *canon;
 
135
 
 
136
      scheme = g_strndup (filename, (strstr (filename, "://") - filename));
 
137
      canon  = g_strdup (scheme);
 
138
 
 
139
      g_strcanon (canon, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "+-.", '-');
 
140
 
 
141
      if (! strcmp (scheme, canon) && g_ascii_isgraph (canon[0]))
 
142
        {
 
143
          g_set_error (error, G_FILE_ERROR, 0,
 
144
                       _("URI scheme '%s:' is not supported"), scheme);
 
145
 
 
146
          g_free (scheme);
 
147
          g_free (canon);
 
148
 
 
149
          return NULL;
 
150
        }
 
151
 
 
152
      g_free (scheme);
 
153
      g_free (canon);
 
154
    }
111
155
 
112
156
  if (! g_path_is_absolute (filename))
113
157
    {
129
173
  return uri;
130
174
}
131
175
 
 
176
gchar *
 
177
file_utils_any_to_uri (Gimp         *gimp,
 
178
                       const gchar  *filename_or_uri,
 
179
                       GError      **error)
 
180
{
 
181
  gchar *uri;
 
182
 
 
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);
 
186
 
 
187
  /*  first try if we got a file uri  */
 
188
  uri = g_filename_from_uri (filename_or_uri, NULL, NULL);
 
189
 
 
190
  if (uri)
 
191
    {
 
192
      g_free (uri);
 
193
      uri = g_strdup (filename_or_uri);
 
194
    }
 
195
  else
 
196
    {
 
197
      uri = file_utils_filename_to_uri (gimp, filename_or_uri, error);
 
198
    }
 
199
 
 
200
  return uri;
 
201
}
 
202
 
 
203
 
132
204
/**
133
205
 * file_utils_filename_from_uri:
134
206
 * @uri: a URI
176
248
  return filename;
177
249
}
178
250
 
179
 
PlugInProcDef *
 
251
GimpPlugInProcedure *
180
252
file_utils_find_proc (GSList       *procs,
181
 
                      const gchar  *uri)
 
253
                      const gchar  *uri,
 
254
                      GError      **error)
182
255
{
183
 
  PlugInProcDef *file_proc;
184
 
  GSList        *all_procs = procs;
185
 
  gchar         *filename;
 
256
  GimpPlugInProcedure *file_proc;
 
257
  GSList              *all_procs = procs;
 
258
  gchar               *filename;
186
259
 
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);
189
263
 
190
264
  /* First, check magicless prefixes/suffixes */
191
265
  file_proc = file_proc_find_by_name (all_procs, uri, TRUE);
198
272
  /* Then look for magics */
199
273
  if (filename)
200
274
    {
201
 
      PlugInProcDef *size_matched_proc = NULL;
202
 
      FILE          *ifp               = NULL;
203
 
      gint           head_size         = -2;
204
 
      gint           size_match_count  = 0;
205
 
      gint           match_val;
206
 
      guchar         head[256];
 
275
      GimpPlugInProcedure *size_matched_proc = NULL;
 
276
      FILE                *ifp               = NULL;
 
277
      gint                 head_size         = -2;
 
278
      gint                 size_match_count  = 0;
 
279
      guchar               head[256];
207
280
 
208
281
      while (procs)
209
282
        {
215
288
              if (head_size == -2)
216
289
                {
217
290
                  head_size = 0;
218
 
                  if ((ifp = fopen (filename, "rb")) != NULL)
219
 
                    head_size = fread ((gchar *) head, 1, sizeof (head), ifp);
 
291
 
 
292
                  if ((ifp = g_fopen (filename, "rb")) != NULL)
 
293
                    {
 
294
                      head_size = fread ((gchar *) head, 1, sizeof (head), ifp);
 
295
                    }
 
296
                  else
 
297
                    {
 
298
                      g_set_error (error,
 
299
                                   G_FILE_ERROR,
 
300
                                   g_file_error_from_errno (errno),
 
301
                                   g_strerror (errno));
 
302
                    }
220
303
                }
221
304
 
222
305
              if (head_size >= 4)
223
306
                {
 
307
                  FileMatchType match_val;
 
308
 
224
309
                  match_val = file_check_magic_list (file_proc->magics_list,
225
310
                                                     head, head_size,
226
311
                                                     ifp);
227
312
 
228
 
                  if (match_val == 2)  /* size match ? */
229
 
                    { /* Use it only if no other magic matches */
 
313
                  if (match_val == FILE_MATCH_SIZE)
 
314
                    {
 
315
                      /* Use it only if no other magic matches */
230
316
                      size_match_count++;
231
317
                      size_matched_proc = file_proc;
232
318
                    }
233
 
                  else if (match_val)
 
319
                  else if (match_val != FILE_MATCH_NONE)
234
320
                    {
235
321
                      fclose (ifp);
236
322
                      g_free (filename);
242
328
        }
243
329
 
244
330
      if (ifp)
245
 
        fclose (ifp);
 
331
        {
 
332
          if (ferror (ifp))
 
333
            g_set_error (error,
 
334
                         G_FILE_ERROR,
 
335
                         g_file_error_from_errno (errno),
 
336
                         g_strerror (errno));
 
337
 
 
338
          fclose (ifp);
 
339
        }
246
340
 
247
341
      g_free (filename);
248
342
 
251
345
    }
252
346
 
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);
 
349
 
 
350
  if (file_proc)
 
351
    {
 
352
      /* we found a procedure, clear error that might have been set */
 
353
      g_clear_error (error);
 
354
    }
 
355
  else
 
356
    {
 
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"));
 
361
    }
 
362
 
 
363
  return file_proc;
255
364
}
256
365
 
257
 
PlugInProcDef *
 
366
GimpPlugInProcedure *
258
367
file_utils_find_proc_by_extension (GSList      *procs,
259
368
                                   const gchar *uri)
260
369
{
265
374
}
266
375
 
267
376
gchar *
268
 
file_utils_uri_to_utf8_basename (const gchar *uri)
269
 
{
270
 
  gchar *filename;
271
 
  gchar *basename;
272
 
 
273
 
  g_return_val_if_fail (uri != NULL, NULL);
274
 
 
275
 
  filename = file_utils_uri_to_utf8_filename (uri);
276
 
 
277
 
  if (strstr (filename, G_DIR_SEPARATOR_S))
278
 
    {
279
 
      basename = g_path_get_basename (filename);
280
 
 
281
 
      g_free (filename);
282
 
 
283
 
      return basename;
284
 
    }
285
 
  else if (strstr (filename, "://"))
286
 
    {
287
 
      basename = strrchr (uri, '/');
288
 
 
289
 
      basename = g_strdup (basename + 1);
290
 
 
291
 
      g_free (filename);
292
 
 
293
 
      return basename;
294
 
    }
295
 
 
296
 
  return filename;
297
 
}
298
 
 
299
 
gchar *
300
377
file_utils_uri_to_utf8_filename (const gchar *uri)
301
378
{
302
379
  g_return_val_if_fail (uri != NULL, NULL);
325
402
  return g_strdup (uri);
326
403
}
327
404
 
 
405
static gchar *
 
406
file_utils_uri_to_utf8_basename (const gchar *uri)
 
407
{
 
408
  gchar *filename;
 
409
  gchar *basename = NULL;
 
410
 
 
411
  g_return_val_if_fail (uri != NULL, NULL);
 
412
 
 
413
  filename = file_utils_uri_to_utf8_filename (uri);
 
414
 
 
415
  if (strstr (filename, G_DIR_SEPARATOR_S))
 
416
    {
 
417
      basename = g_path_get_basename (filename);
 
418
    }
 
419
  else if (strstr (filename, "://"))
 
420
    {
 
421
      basename = strrchr (uri, '/');
 
422
 
 
423
      if (basename)
 
424
        basename = g_strdup (basename + 1);
 
425
    }
 
426
 
 
427
  if (basename)
 
428
    {
 
429
      g_free (filename);
 
430
      return basename;
 
431
    }
 
432
 
 
433
  return filename;
 
434
}
 
435
 
 
436
gchar *
 
437
file_utils_uri_display_basename (const gchar *uri)
 
438
{
 
439
  gchar *basename = NULL;
 
440
 
 
441
  g_return_val_if_fail (uri != NULL, NULL);
 
442
 
 
443
  if (g_str_has_prefix (uri, "file:"))
 
444
    {
 
445
      gchar *filename = file_utils_filename_from_uri (uri);
 
446
 
 
447
      if (filename)
 
448
        {
 
449
          basename = g_filename_display_basename (filename);
 
450
          g_free (filename);
 
451
        }
 
452
    }
 
453
  else
 
454
    {
 
455
      gchar *name = file_utils_uri_display_name (uri);
 
456
 
 
457
      basename = strrchr (name, '/');
 
458
      if (basename)
 
459
        basename = g_strdup (basename + 1);
 
460
 
 
461
      g_free (name);
 
462
    }
 
463
 
 
464
  return basename ? basename : file_utils_uri_to_utf8_basename (uri);
 
465
}
 
466
 
 
467
gchar *
 
468
file_utils_uri_display_name (const gchar *uri)
 
469
{
 
470
  gchar *name = NULL;
 
471
 
 
472
  g_return_val_if_fail (uri != NULL, NULL);
 
473
 
 
474
  if (g_str_has_prefix (uri, "file:"))
 
475
    {
 
476
      gchar *filename = file_utils_filename_from_uri (uri);
 
477
 
 
478
      if (filename)
 
479
        {
 
480
          name = g_filename_display_name (filename);
 
481
          g_free (filename);
 
482
        }
 
483
    }
 
484
  else
 
485
    {
 
486
      name = file_utils_unescape_uri (uri, -1, "/", FALSE);
 
487
    }
 
488
 
 
489
  return name ? name : g_strdup (uri);
 
490
}
 
491
 
 
492
GdkPixbuf *
 
493
file_utils_load_thumbnail (const gchar *filename)
 
494
{
 
495
  GimpThumbnail *thumbnail = NULL;
 
496
  GdkPixbuf     *pixbuf    = NULL;
 
497
  gchar         *uri;
 
498
 
 
499
  g_return_val_if_fail (filename != NULL, NULL);
 
500
 
 
501
  uri = g_filename_to_uri (filename, NULL, NULL);
 
502
 
 
503
  if (uri)
 
504
    {
 
505
      thumbnail = gimp_thumbnail_new ();
 
506
      gimp_thumbnail_set_uri (thumbnail, uri);
 
507
 
 
508
      pixbuf = gimp_thumbnail_load_thumb (thumbnail,
 
509
                                          GIMP_THUMBNAIL_SIZE_NORMAL,
 
510
                                          NULL);
 
511
    }
 
512
 
 
513
  g_free (uri);
 
514
 
 
515
  if (pixbuf)
 
516
    {
 
517
      gint width  = gdk_pixbuf_get_width (pixbuf);
 
518
      gint height = gdk_pixbuf_get_height (pixbuf);
 
519
 
 
520
      if (gdk_pixbuf_get_n_channels (pixbuf) != 3)
 
521
        {
 
522
          GdkPixbuf *tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
 
523
                                           width, height);
 
524
 
 
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);
 
530
 
 
531
          g_object_unref (pixbuf);
 
532
          pixbuf = tmp;
 
533
        }
 
534
    }
 
535
 
 
536
  return pixbuf;
 
537
}
 
538
 
 
539
gboolean
 
540
file_utils_save_thumbnail (GimpImage   *image,
 
541
                           const gchar *filename)
 
542
{
 
543
  const gchar *image_uri;
 
544
  gboolean     success = FALSE;
 
545
 
 
546
  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
 
547
  g_return_val_if_fail (filename != NULL, FALSE);
 
548
 
 
549
  image_uri = gimp_object_get_name (GIMP_OBJECT (image));
 
550
 
 
551
  if (image_uri)
 
552
    {
 
553
      gchar *uri = g_filename_to_uri (filename, NULL, NULL);
 
554
 
 
555
      if (uri)
 
556
        {
 
557
          if ( ! strcmp (uri, image_uri))
 
558
            {
 
559
              GimpImagefile *imagefile;
 
560
 
 
561
              imagefile = gimp_imagefile_new (image->gimp, uri);
 
562
              success = gimp_imagefile_save_thumbnail (imagefile, NULL, image);
 
563
              g_object_unref (imagefile);
 
564
            }
 
565
 
 
566
          g_free (uri);
 
567
        }
 
568
    }
 
569
 
 
570
  return success;
 
571
}
 
572
 
328
573
 
329
574
/*  private functions  */
330
575
 
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)
337
582
 
338
583
  for (p = procs; p; p = g_slist_next (p))
339
584
    {
340
 
      PlugInProcDef *proc = p->data;
341
 
      GSList        *prefixes;
 
585
      GimpPlugInProcedure *proc = p->data;
 
586
      GSList              *prefixes;
342
587
 
343
588
      if (skip_magic && proc->magics_list)
344
 
        continue;
 
589
        continue;
345
590
 
346
591
      for (prefixes = proc->prefixes_list;
347
 
           prefixes;
348
 
           prefixes = g_slist_next (prefixes))
349
 
        {
350
 
          if (strncmp (uri, prefixes->data, strlen (prefixes->data)) == 0)
351
 
            return proc;
352
 
        }
 
592
           prefixes;
 
593
           prefixes = g_slist_next (prefixes))
 
594
        {
 
595
          if (g_str_has_prefix (uri, prefixes->data))
 
596
            return proc;
 
597
        }
353
598
     }
354
599
 
355
600
  return NULL;
356
601
}
357
602
 
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)
370
615
 
371
616
  for (p = procs; p; p = g_slist_next (p))
372
617
    {
373
 
      PlugInProcDef *proc = p->data;
374
 
      GSList        *extensions;
 
618
      GimpPlugInProcedure *proc = p->data;
 
619
      GSList              *extensions;
375
620
 
376
621
      for (extensions = proc->extensions_list;
377
 
           ext && extensions;
378
 
           extensions = g_slist_next (extensions))
379
 
        {
380
 
          const gchar *p1 = ext;
381
 
          const gchar *p2 = extensions->data;
 
622
           ext && extensions;
 
623
           extensions = g_slist_next (extensions))
 
624
        {
 
625
          const gchar *p1 = ext;
 
626
          const gchar *p2 = extensions->data;
382
627
 
383
628
          if (skip_magic && proc->magics_list)
384
 
            continue;
385
 
 
386
 
          while (*p1 && *p2)
387
 
            {
388
 
              if (g_ascii_tolower (*p1) != g_ascii_tolower (*p2))
389
 
                break;
390
 
 
391
 
              p1++;
392
 
              p2++;
393
 
            }
394
 
 
395
 
          if (!(*p1) && !(*p2))
396
 
            return proc;
397
 
        }
 
629
            continue;
 
630
 
 
631
          while (*p1 && *p2)
 
632
            {
 
633
              if (g_ascii_tolower (*p1) != g_ascii_tolower (*p2))
 
634
                break;
 
635
 
 
636
              p1++;
 
637
              p2++;
 
638
            }
 
639
 
 
640
          if (!(*p1) && !(*p2))
 
641
            return proc;
 
642
        }
398
643
    }
399
644
 
400
645
  return NULL;
401
646
}
402
647
 
403
 
static PlugInProcDef *
 
648
static GimpPlugInProcedure *
404
649
file_proc_find_by_name (GSList      *procs,
405
 
                        const gchar *uri,
406
 
                        gboolean     skip_magic)
 
650
                        const gchar *uri,
 
651
                        gboolean     skip_magic)
407
652
{
408
 
  PlugInProcDef *proc;
 
653
  GimpPlugInProcedure *proc;
409
654
 
410
655
  proc = file_proc_find_by_prefix (procs, uri, skip_magic);
411
656
 
415
660
  return proc;
416
661
}
417
662
 
 
663
 
 
664
/* the following two functions are copied from glib/gconvert.c */
 
665
 
 
666
static gint
 
667
unescape_character (const gchar *scanner)
 
668
{
 
669
  gint first_digit;
 
670
  gint second_digit;
 
671
 
 
672
  first_digit = g_ascii_xdigit_value (scanner[0]);
 
673
  if (first_digit < 0)
 
674
    return -1;
 
675
 
 
676
  second_digit = g_ascii_xdigit_value (scanner[1]);
 
677
  if (second_digit < 0)
 
678
    return -1;
 
679
 
 
680
  return (first_digit << 4) | second_digit;
 
681
}
 
682
 
 
683
static gchar *
 
684
file_utils_unescape_uri (const gchar *escaped,
 
685
                         gint         len,
 
686
                         const gchar *illegal_escaped_characters,
 
687
                         gboolean     ascii_must_not_be_escaped)
 
688
{
 
689
  const gchar *in, *in_end;
 
690
  gchar *out, *result;
 
691
  gint c;
 
692
 
 
693
  if (escaped == NULL)
 
694
    return NULL;
 
695
 
 
696
  if (len < 0)
 
697
    len = strlen (escaped);
 
698
 
 
699
  result = g_malloc (len + 1);
 
700
 
 
701
  out = result;
 
702
  for (in = escaped, in_end = escaped + len; in < in_end; in++)
 
703
    {
 
704
      c = *in;
 
705
 
 
706
      if (c == '%')
 
707
        {
 
708
          /* catch partial escape sequences past the end of the substring */
 
709
          if (in + 3 > in_end)
 
710
            break;
 
711
 
 
712
          c = unescape_character (in + 1);
 
713
 
 
714
          /* catch bad escape sequences and NUL characters */
 
715
          if (c <= 0)
 
716
            break;
 
717
 
 
718
          /* catch escaped ASCII */
 
719
          if (ascii_must_not_be_escaped && c <= 0x7F)
 
720
            break;
 
721
 
 
722
          /* catch other illegal escaped characters */
 
723
          if (strchr (illegal_escaped_characters, c) != NULL)
 
724
            break;
 
725
 
 
726
          in += 2;
 
727
        }
 
728
 
 
729
      *out++ = c;
 
730
    }
 
731
 
 
732
  g_assert (out - result <= len);
 
733
  *out = '\0';
 
734
 
 
735
  if (in != in_end)
 
736
    {
 
737
      g_free (result);
 
738
      return NULL;
 
739
    }
 
740
 
 
741
  return result;
 
742
}
 
743
 
418
744
static void
419
745
file_convert_string (const gchar *instr,
420
 
                     gchar       *outmem,
421
 
                     gint         maxmem,
422
 
                     gint        *nmem)
 
746
                     gchar       *outmem,
 
747
                     gint         maxmem,
 
748
                     gint        *nmem)
423
749
{
424
750
  /* Convert a string in C-notation to array of char */
425
751
  const guchar *uin  = (const guchar *) instr;
472
798
  *nmem = ((gchar *) uout) - outmem;
473
799
}
474
800
 
475
 
static gint
 
801
static FileMatchType
476
802
file_check_single_magic (const gchar  *offset,
477
803
                         const gchar  *type,
478
804
                         const gchar  *value,
481
807
                         FILE         *ifp)
482
808
 
483
809
{
484
 
  /* Return values are 0: no match, 1: magic match, 2: size match */
 
810
  FileMatchType found = FILE_MATCH_NONE;
485
811
  glong         offs;
486
 
  gulong        num_testval, num_operatorval;
487
 
  gulong        fileval;
 
812
  gulong        num_testval;
 
813
  gulong        num_operatorval;
488
814
  gint          numbytes, k;
489
 
  gint          c     = 0;
490
 
  gint          found = 0;
491
815
  const gchar  *num_operator_ptr;
492
816
  gchar         num_operator;
493
 
  gchar         num_test;
494
 
  guchar        mem_testval[256];
495
817
 
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;
499
821
 
500
822
  /* Check type of test */
501
823
  num_operator_ptr = NULL;
502
824
  num_operator     = '\0';
503
 
  num_test         = '=';
504
825
 
505
 
  if (strncmp (type, "byte", 4) == 0)
 
826
  if (g_str_has_prefix (type, "byte"))
506
827
    {
507
828
      numbytes = 1;
508
 
      num_operator_ptr = type + 4;
 
829
      num_operator_ptr = type + strlen ("byte");
509
830
    }
510
 
  else if (strncmp (type, "short", 5) == 0)
 
831
  else if (g_str_has_prefix (type, "short"))
511
832
    {
512
833
      numbytes = 2;
513
 
      num_operator_ptr = type + 5;
 
834
      num_operator_ptr = type + strlen ("short");
514
835
    }
515
 
  else if (strncmp (type, "long", 4) == 0)
 
836
  else if (g_str_has_prefix (type, "long"))
516
837
    {
517
838
      numbytes = 4;
518
 
      num_operator_ptr = type + 4;
 
839
      num_operator_ptr = type + strlen ("long");
519
840
    }
520
 
  else if (strncmp (type, "size", 4) == 0)
 
841
  else if (g_str_has_prefix (type, "size"))
521
842
    {
522
843
      numbytes = 5;
523
844
    }
525
846
    {
526
847
      numbytes = 0;
527
848
    }
528
 
  else return (0);
 
849
  else
 
850
    {
 
851
      return FILE_MATCH_NONE;
 
852
    }
529
853
 
530
854
  /* Check numerical operator value if present */
531
855
  if (num_operator_ptr && (*num_operator_ptr == '&'))
538
862
            sscanf (num_operator_ptr+3, "%lx", &num_operatorval);
539
863
          else                                 /* octal */
540
864
            sscanf (num_operator_ptr+2, "%lo", &num_operatorval);
 
865
 
541
866
          num_operator = *num_operator_ptr;
542
867
        }
543
868
    }
544
869
 
545
870
  if (numbytes > 0)   /* Numerical test ? */
546
871
    {
 
872
      gchar   num_test = '=';
 
873
      gulong  fileval  = 0;
 
874
 
547
875
      /* Check test value */
548
 
      if ((value[0] == '=') || (value[0] == '>') || (value[0] == '<'))
549
 
      {
550
 
        num_test = value[0];
551
 
        value++;
552
 
      }
553
 
      if (!g_ascii_isdigit (value[0])) return (0);
554
 
 
555
 
      /*
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?
559
 
       * */
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);
564
 
      else                      /* octal */
565
 
        num_testval = strtol(value+1, NULL, 8);
566
 
 
567
 
      fileval = 0;
 
876
      if ((value[0] == '>') || (value[0] == '<'))
 
877
        {
 
878
          num_test = value[0];
 
879
          value++;
 
880
        }
 
881
 
 
882
      errno = 0;
 
883
      num_testval = strtol (value, NULL, 0);
 
884
 
 
885
      if (errno != 0)
 
886
        return FILE_MATCH_NONE;
 
887
 
568
888
      if (numbytes == 5)    /* Check for file size ? */
569
889
        {
570
 
          struct stat buf;
571
 
 
572
 
          if (fstat (fileno (ifp), &buf) < 0) return (0);
 
890
          struct stat buf;
 
891
 
 
892
          if (fstat (fileno (ifp), &buf) < 0)
 
893
            return FILE_MATCH_NONE;
 
894
 
573
895
          fileval = buf.st_size;
574
896
        }
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 ? */
576
899
        {
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];
579
902
        }
580
903
      else   /* Read it from file */
581
904
        {
582
 
          if (fseek (ifp, offs, SEEK_SET) < 0) return (0);
 
905
          gint c = 0;
 
906
 
 
907
          if (fseek (ifp, offs, (offs >= 0) ? SEEK_SET : SEEK_END) < 0)
 
908
            return FILE_MATCH_NONE;
 
909
 
583
910
          for (k = 0; k < numbytes; k++)
584
911
            fileval = (fileval << 8) | (c = getc (ifp));
585
 
          if (c == EOF) return (0);
 
912
 
 
913
          if (c == EOF)
 
914
            return FILE_MATCH_NONE;
586
915
        }
 
916
 
587
917
      if (num_operator == '&')
588
918
        fileval &= num_operatorval;
589
919
 
594
924
      else
595
925
        found = (fileval == num_testval);
596
926
 
597
 
      if (found && (numbytes == 5)) found = 2;
 
927
      if (found && (numbytes == 5))
 
928
        found = FILE_MATCH_SIZE;
598
929
    }
599
930
  else if (numbytes == 0) /* String test */
600
931
    {
 
932
      gchar mem_testval[256];
 
933
 
601
934
      file_convert_string (value,
602
935
                           mem_testval, sizeof (mem_testval),
603
936
                           &numbytes);
604
937
 
605
 
      if (numbytes <= 0) return (0);
 
938
      if (numbytes <= 0)
 
939
        return FILE_MATCH_NONE;
606
940
 
607
 
      if (offs + numbytes <= headsize)  /* We have it in memory ? */
 
941
      if (offs >= 0 &&
 
942
          (offs + numbytes <= headsize)) /* We have it in memory ? */
608
943
        {
609
 
          found = (memcmp (mem_testval, file_head+offs, numbytes) == 0);
 
944
          found = (memcmp (mem_testval, file_head + offs, numbytes) == 0);
610
945
        }
611
946
      else   /* Read it from file */
612
947
        {
613
 
          if (fseek (ifp, offs, SEEK_SET) < 0) return (0);
614
 
          found = 1;
 
948
          if (fseek (ifp, offs, (offs >= 0) ? SEEK_SET : SEEK_END) < 0)
 
949
            return FILE_MATCH_NONE;
 
950
 
 
951
          found = FILE_MATCH_MAGIC;
 
952
 
615
953
          for (k = 0; found && (k < numbytes); k++)
616
954
            {
617
 
              c = getc (ifp);
618
 
              found = (c != EOF) && (c == (int)mem_testval[k]);
 
955
              gint c = getc (ifp);
 
956
 
 
957
              found = (c != EOF) && (c == (gint) mem_testval[k]);
619
958
            }
620
959
        }
621
960
    }
623
962
  return found;
624
963
}
625
964
 
626
 
/*
627
 
 *  Return values are 0: no match, 1: magic match, 2: size match
628
 
 */
629
 
static gint
 
965
static FileMatchType
630
966
file_check_magic_list (GSList       *magics_list,
631
 
                       const guchar *head,
632
 
                       gint          headsize,
633
 
                       FILE         *ifp)
 
967
                       const guchar *head,
 
968
                       gint          headsize,
 
969
                       FILE         *ifp)
634
970
 
635
971
{
636
 
  const gchar *offset;
637
 
  const gchar *type;
638
 
  const gchar *value;
639
 
  gint         and   = 0;
640
 
  gint         found = 0;
641
 
  gint         match_val;
 
972
  const gchar   *offset;
 
973
  const gchar   *type;
 
974
  const gchar   *value;
 
975
  gboolean       and   = FALSE;
 
976
  gboolean       found = FALSE;
 
977
  FileMatchType  match_val;
642
978
 
643
979
  while (magics_list)
644
980
    {
654
990
                                           head, headsize,
655
991
                                           ifp);
656
992
      if (and)
657
 
        found = found && match_val;
 
993
        found = found && (match_val != FILE_MATCH_NONE);
658
994
      else
659
 
        found = match_val;
 
995
        found = (match_val != FILE_MATCH_NONE);
660
996
 
661
997
      and = (strchr (offset, '&') != NULL);
662
998
 
663
 
      if ((!and) && found)
664
 
        return match_val;
 
999
      if (! and && found)
 
1000
        return match_val;
665
1001
    }
666
1002
 
667
 
  return 0;
 
1003
  return FILE_MATCH_NONE;
668
1004
}