~ubuntu-branches/ubuntu/breezy/gimp/breezy

« back to all changes in this revision

Viewing changes to libgimpthumb/gimpthumb-utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2005-10-04 19:04:46 UTC
  • Revision ID: james.westby@ubuntu.com-20051004190446-ukh32kwk56s4sjhu
Tags: upstream-2.2.8
ImportĀ upstreamĀ versionĀ 2.2.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* LIBGIMP - The GIMP Library
 
2
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
 
3
 *
 
4
 * Thumbnail handling according to the Thumbnail Managing Standard.
 
5
 * http://triq.net/~pearl/thumbnail-spec/
 
6
 *
 
7
 * Copyright (C) 2001-2003  Sven Neumann <sven@gimp.org>
 
8
 *                          Michael Natterer <mitch@gimp.org>
 
9
 *
 
10
 * This library is free software; you can redistribute it and/or
 
11
 * modify it under the terms of the GNU Lesser General Public
 
12
 * License as published by the Free Software Foundation; either
 
13
 * version 2 of the License, or (at your option) any later version.
 
14
 *
 
15
 * This library is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
 * Lesser General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU Lesser General Public
 
21
 * License along with this library; if not, write to the
 
22
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
23
 * Boston, MA 02111-1307, USA.
 
24
 */
 
25
 
 
26
#include "config.h"
 
27
 
 
28
#include <errno.h>
 
29
#include <string.h>
 
30
#include <sys/types.h>
 
31
#include <sys/stat.h>
 
32
#ifdef HAVE_UNISTD_H
 
33
#include <unistd.h>
 
34
#endif
 
35
 
 
36
#include <glib-object.h>
 
37
 
 
38
#ifdef G_OS_WIN32
 
39
#include "libgimpbase/gimpwin32-io.h"
 
40
#endif
 
41
 
 
42
#include "libgimpmath/gimpmath.h"
 
43
 
 
44
#include "gimpthumb-error.h"
 
45
#include "gimpthumb-types.h"
 
46
#include "gimpthumb-utils.h"
 
47
 
 
48
#include "libgimp/libgimp-intl.h"
 
49
 
 
50
 
 
51
static gint           gimp_thumb_size       (GimpThumbSize  size);
 
52
static gchar        * gimp_thumb_png_lookup (const gchar   *name,
 
53
                                             const gchar   *basedir,
 
54
                                             GimpThumbSize *size);
 
55
static const gchar  * gimp_thumb_png_name   (const gchar   *uri);
 
56
static void           gimp_thumb_exit       (void);
 
57
 
 
58
 
 
59
 
 
60
static gboolean      gimp_thumb_initialized = FALSE;
 
61
static gint          thumb_num_sizes        = 0;
 
62
static gint         *thumb_sizes            = NULL;
 
63
static const gchar **thumb_sizenames        = NULL;
 
64
static gchar        *thumb_dir              = NULL;
 
65
static gchar       **thumb_subdirs          = NULL;
 
66
static gchar        *thumb_fail_subdir      = NULL;
 
67
 
 
68
 
 
69
/**
 
70
 * gimp_thumb_init:
 
71
 * @creator: an ASCII string that identifies the thumbnail creator
 
72
 * @thumb_basedir: an absolute path or %NULL to use the default
 
73
 *
 
74
 * This function initializes the thumbnail system. It must be called
 
75
 * before any other functions from libgimpthumb are used. You may call
 
76
 * it more than once if you want to change the @thumb_basedir but if
 
77
 * you do that, you should make sure that no thread is still using the
 
78
 * library. Apart from this function, libgimpthumb is multi-thread
 
79
 * safe.
 
80
 *
 
81
 * The @creator string must be 7bit ASCII and should contain the name
 
82
 * of the software that creates the thumbnails. It is used to handle
 
83
 * thumbnail creation failures. See the spec for more details.
 
84
 *
 
85
 * Usually you will pass %NULL for @thumb_basedir. Thumbnails will
 
86
 * then be stored in the user's personal thumbnail directory as
 
87
 * defined in the spec. If you wish to use libgimpthumb to store
 
88
 * application-specific thumbnails, you can specify a different base
 
89
 * directory here.
 
90
 *
 
91
 * Return value: %TRUE if the library was successfully initialized.
 
92
 **/
 
93
gboolean
 
94
gimp_thumb_init (const gchar *creator,
 
95
                 const gchar *thumb_basedir)
 
96
{
 
97
  GEnumClass *enum_class;
 
98
  GEnumValue *enum_value;
 
99
  gint        i;
 
100
 
 
101
  g_return_val_if_fail (creator != NULL, FALSE);
 
102
  g_return_val_if_fail (thumb_basedir == NULL ||
 
103
                        g_path_is_absolute (thumb_basedir), FALSE);
 
104
 
 
105
  if (gimp_thumb_initialized)
 
106
    gimp_thumb_exit ();
 
107
 
 
108
  if (thumb_basedir)
 
109
    {
 
110
      thumb_dir = g_strdup (thumb_basedir);
 
111
    }
 
112
  else
 
113
    {
 
114
      const gchar *home_dir = g_get_home_dir ();
 
115
 
 
116
      if (home_dir && g_file_test (home_dir, G_FILE_TEST_IS_DIR))
 
117
        {
 
118
          thumb_dir = g_build_filename (home_dir, ".thumbnails", NULL);
 
119
        }
 
120
      else
 
121
        {
 
122
          gchar *name =
 
123
            g_filename_to_utf8 (g_get_tmp_dir (), -1, NULL, NULL, NULL);
 
124
 
 
125
          g_message (_("Cannot determine a valid home directory.\n"
 
126
                       "Thumbnails will be stored in the folder for "
 
127
                       "temporary files (%s) instead."), name);
 
128
          g_free (name);
 
129
 
 
130
          thumb_dir = g_build_filename (g_get_tmp_dir (), ".thumbnails", NULL);
 
131
        }
 
132
    }
 
133
 
 
134
  enum_class = g_type_class_ref (GIMP_TYPE_THUMB_SIZE);
 
135
 
 
136
  thumb_num_sizes = enum_class->n_values;
 
137
  thumb_sizes     = g_new (gint, thumb_num_sizes);
 
138
  thumb_sizenames = g_new (const gchar *, thumb_num_sizes);
 
139
  thumb_subdirs   = g_new (gchar *, thumb_num_sizes);
 
140
 
 
141
  for (i = 0, enum_value = enum_class->values;
 
142
       i < enum_class->n_values;
 
143
       i++, enum_value++)
 
144
    {
 
145
      thumb_sizes[i]     = enum_value->value;
 
146
      thumb_sizenames[i] = enum_value->value_nick;
 
147
      thumb_subdirs[i]   = g_build_filename (thumb_dir,
 
148
                                             enum_value->value_nick, NULL);
 
149
    }
 
150
 
 
151
  thumb_fail_subdir = thumb_subdirs[0];
 
152
  thumb_subdirs[0]  = g_build_filename (thumb_fail_subdir, creator, NULL);
 
153
 
 
154
  g_type_class_unref (enum_class);
 
155
 
 
156
  gimp_thumb_initialized = TRUE;
 
157
 
 
158
  return gimp_thumb_initialized;
 
159
}
 
160
 
 
161
/**
 
162
 * gimp_thumb_get_thumb_dir:
 
163
 * @size: a GimpThumbSize
 
164
 *
 
165
 * Retrieve the name of the thumbnail folder for a specific size. The
 
166
 * returned pointer will become invalid if gimp_thumb_init() is used
 
167
 * again. It must not be changed or freed.
 
168
 *
 
169
 * Return value: the thumbnail directory in the encoding of the filesystem
 
170
 **/
 
171
const gchar *
 
172
gimp_thumb_get_thumb_dir (GimpThumbSize  size)
 
173
{
 
174
  g_return_val_if_fail (gimp_thumb_initialized, NULL);
 
175
 
 
176
  size = gimp_thumb_size (size);
 
177
 
 
178
  return thumb_subdirs[size];
 
179
}
 
180
 
 
181
/**
 
182
 * gimp_thumb_get_thumb_dir_local:
 
183
 * @dirname:
 
184
 * @size: a GimpThumbSize
 
185
 *
 
186
 * Retrieve the name of the local thumbnail folder for a specific
 
187
 * size.  Unlike gimp_thumb_get_thumb_dir() the returned string is not
 
188
 * constant and should be free'd when it is not any longer needed.
 
189
 *
 
190
 * Return value: the thumbnail directory in the encoding of the filesystem
 
191
 *
 
192
 * Since: GIMP 2.2
 
193
 **/
 
194
gchar *
 
195
gimp_thumb_get_thumb_dir_local (const gchar   *dirname,
 
196
                                GimpThumbSize  size)
 
197
{
 
198
  g_return_val_if_fail (gimp_thumb_initialized, NULL);
 
199
  g_return_val_if_fail (dirname != NULL, NULL);
 
200
  g_return_val_if_fail (size > GIMP_THUMB_SIZE_FAIL, NULL);
 
201
 
 
202
  size = gimp_thumb_size (size);
 
203
 
 
204
  return g_build_filename (dirname, thumb_sizenames[size], NULL);
 
205
}
 
206
 
 
207
/**
 
208
 * gimp_thumb_ensure_thumb_dir:
 
209
 * @size: a GimpThumbSize
 
210
 * @error: return location for possible errors
 
211
 *
 
212
 * This function checks if the directory that is required to store
 
213
 * thumbnails for a particular @size exist and attempts to create it
 
214
 * if necessary.
 
215
 *
 
216
 * You shouldn't have to call this function directly since
 
217
 * gimp_thumbnail_save_thumb() and gimp_thumbnail_save_failure() will
 
218
 * do this for you.
 
219
 *
 
220
 * Return value: %TRUE is the directory exists, %FALSE if it could not
 
221
 *               be created
 
222
 **/
 
223
gboolean
 
224
gimp_thumb_ensure_thumb_dir (GimpThumbSize   size,
 
225
                             GError        **error)
 
226
{
 
227
  g_return_val_if_fail (gimp_thumb_initialized, FALSE);
 
228
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
229
 
 
230
  size = gimp_thumb_size (size);
 
231
 
 
232
  if (g_file_test (thumb_subdirs[size], G_FILE_TEST_IS_DIR))
 
233
    return TRUE;
 
234
 
 
235
  if (g_file_test (thumb_dir, G_FILE_TEST_IS_DIR) ||
 
236
      (mkdir (thumb_dir, S_IRUSR | S_IWUSR | S_IXUSR) == 0))
 
237
    {
 
238
      if (size == 0)
 
239
        mkdir (thumb_fail_subdir, S_IRUSR | S_IWUSR | S_IXUSR);
 
240
 
 
241
      mkdir (thumb_subdirs[size], S_IRUSR | S_IWUSR | S_IXUSR);
 
242
    }
 
243
 
 
244
  if (g_file_test (thumb_subdirs[size], G_FILE_TEST_IS_DIR))
 
245
    return TRUE;
 
246
 
 
247
  g_set_error (error,
 
248
               GIMP_THUMB_ERROR, GIMP_THUMB_ERROR_MKDIR,
 
249
               _("Failed to create thumbnail folder '%s'."),
 
250
               thumb_subdirs[size]);
 
251
 
 
252
  return FALSE;
 
253
}
 
254
 
 
255
/**
 
256
 * gimp_thumb_ensure_thumb_dir_local:
 
257
 * @dirname:
 
258
 * @size: a GimpThumbSize
 
259
 * @error: return location for possible errors
 
260
 *
 
261
 * This function checks if the directory that is required to store
 
262
 * local thumbnails for a particular @size exist and attempts to
 
263
 * create it if necessary.
 
264
 *
 
265
 * You shouldn't have to call this function directly since
 
266
 * gimp_thumbnail_save_thumb_local() will do this for you.
 
267
 *
 
268
 * Return value: %TRUE is the directory exists, %FALSE if it could not
 
269
 *               be created
 
270
 *
 
271
 * Since: GIMP 2.2
 
272
 **/
 
273
gboolean
 
274
gimp_thumb_ensure_thumb_dir_local (const gchar    *dirname,
 
275
                                   GimpThumbSize   size,
 
276
                                   GError        **error)
 
277
{
 
278
  gchar *basedir;
 
279
  gchar *subdir;
 
280
 
 
281
  g_return_val_if_fail (gimp_thumb_initialized, FALSE);
 
282
  g_return_val_if_fail (dirname != NULL, FALSE);
 
283
  g_return_val_if_fail (g_path_is_absolute (dirname), FALSE);
 
284
  g_return_val_if_fail (size > GIMP_THUMB_SIZE_FAIL, FALSE);
 
285
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
286
 
 
287
  size = gimp_thumb_size (size);
 
288
 
 
289
  subdir = g_build_filename (dirname,
 
290
                             ".thumblocal", thumb_sizenames[size],
 
291
                             NULL);
 
292
 
 
293
  if (g_file_test (subdir, G_FILE_TEST_IS_DIR))
 
294
    {
 
295
      g_free (subdir);
 
296
      return TRUE;
 
297
    }
 
298
 
 
299
  basedir = g_build_filename (dirname, ".thumblocal", NULL);
 
300
 
 
301
  if (g_file_test (basedir, G_FILE_TEST_IS_DIR) ||
 
302
      (mkdir (thumb_dir, S_IRUSR | S_IWUSR | S_IXUSR) == 0))
 
303
    {
 
304
      mkdir (subdir, S_IRUSR | S_IWUSR | S_IXUSR);
 
305
    }
 
306
 
 
307
  g_free (basedir);
 
308
 
 
309
  if (g_file_test (subdir, G_FILE_TEST_IS_DIR))
 
310
    {
 
311
      g_free (subdir);
 
312
      return TRUE;
 
313
    }
 
314
 
 
315
  g_set_error (error,
 
316
               GIMP_THUMB_ERROR, GIMP_THUMB_ERROR_MKDIR,
 
317
               _("Failed to create thumbnail folder '%s'."),
 
318
               subdir);
 
319
  g_free (subdir);
 
320
 
 
321
  return FALSE;
 
322
}
 
323
 
 
324
/**
 
325
 * gimp_thumb_name_from_uri:
 
326
 * @uri: an escaped URI
 
327
 * @size: a #GimpThumbSize
 
328
 *
 
329
 * Creates the name of the thumbnail file of the specified @size that
 
330
 * belongs to an image file located at the given @uri.
 
331
 *
 
332
 * Return value: a newly allocated filename in the encoding of the
 
333
 *               filesystem or %NULL if @uri points to the user's
 
334
 *               thumbnail repository.
 
335
 **/
 
336
gchar *
 
337
gimp_thumb_name_from_uri (const gchar   *uri,
 
338
                          GimpThumbSize  size)
 
339
{
 
340
  g_return_val_if_fail (gimp_thumb_initialized, NULL);
 
341
  g_return_val_if_fail (uri != NULL, NULL);
 
342
 
 
343
  if (strstr (uri, thumb_dir))
 
344
    return NULL;
 
345
 
 
346
  size = gimp_thumb_size (size);
 
347
 
 
348
  return g_build_filename (thumb_subdirs[size],
 
349
                           gimp_thumb_png_name (uri),
 
350
                           NULL);
 
351
}
 
352
 
 
353
/**
 
354
 * gimp_thumb_name_from_uri_local:
 
355
 * @uri: an escaped URI
 
356
 * @size: a #GimpThumbSize
 
357
 *
 
358
 * Creates the name of a local thumbnail file of the specified @size
 
359
 * that belongs to an image file located at the given @uri. Local
 
360
 * thumbnails have been introduced with version 0.7 of the spec.
 
361
 *
 
362
 * Return value: a newly allocated filename in the encoding of the
 
363
 *               filesystem or %NULL if @uri is a remote file or
 
364
 *               points to the user's thumbnail repository.
 
365
 *
 
366
 * Since: GIMP 2.2
 
367
 **/
 
368
gchar *
 
369
gimp_thumb_name_from_uri_local (const gchar   *uri,
 
370
                                GimpThumbSize  size)
 
371
{
 
372
  gchar *filename;
 
373
  gchar *result = NULL;
 
374
 
 
375
  g_return_val_if_fail (gimp_thumb_initialized, NULL);
 
376
  g_return_val_if_fail (uri != NULL, NULL);
 
377
  g_return_val_if_fail (size > GIMP_THUMB_SIZE_FAIL, NULL);
 
378
 
 
379
  if (strstr (uri, thumb_dir))
 
380
    return NULL;
 
381
 
 
382
  filename = _gimp_thumb_filename_from_uri (uri);
 
383
 
 
384
  if (filename)
 
385
    {
 
386
      const gchar *baseuri = strrchr (uri, '/');
 
387
 
 
388
      if (baseuri && baseuri[0] && baseuri[1])
 
389
        {
 
390
          gchar *dirname = g_path_get_dirname (filename);
 
391
          gint   i       = gimp_thumb_size (size);
 
392
 
 
393
          result = g_build_filename (dirname,
 
394
                                     ".thumblocal", thumb_sizenames[i],
 
395
                                     gimp_thumb_png_name (uri),
 
396
                                     NULL);
 
397
 
 
398
          g_free (dirname);
 
399
        }
 
400
 
 
401
      g_free (filename);
 
402
    }
 
403
 
 
404
  return result;
 
405
}
 
406
 
 
407
/**
 
408
 * gimp_thumb_find_thumb:
 
409
 * @uri: an escaped URI
 
410
 * @size: pointer to a #GimpThumbSize
 
411
 *
 
412
 * This function attempts to locate a thumbnail for the given
 
413
 * @uri. First it tries the size that is stored at @size. If no
 
414
 * thumbnail of that size is found, it will look for a larger
 
415
 * thumbnail, then falling back to a smaller size.
 
416
 *
 
417
 * If the user's thumbnail repository doesn't provide a thumbnail but
 
418
 * a local thumbnail repository exists for the folder the image is
 
419
 * located in, the same search is done among the local thumbnails (if
 
420
 * there are any).
 
421
 *
 
422
 * If a thumbnail is found, it's size is written to the variable
 
423
 * pointer to by @size and the file location is returned.
 
424
 *
 
425
 * Return value: a newly allocated string in the encoding of the
 
426
 *               filesystem or %NULL if no thumbnail for @uri was found
 
427
 **/
 
428
gchar *
 
429
gimp_thumb_find_thumb (const gchar   *uri,
 
430
                       GimpThumbSize *size)
 
431
{
 
432
  gchar *result;
 
433
 
 
434
  g_return_val_if_fail (gimp_thumb_initialized, NULL);
 
435
  g_return_val_if_fail (uri != NULL, NULL);
 
436
  g_return_val_if_fail (size != NULL, NULL);
 
437
  g_return_val_if_fail (*size > GIMP_THUMB_SIZE_FAIL, NULL);
 
438
 
 
439
  result = gimp_thumb_png_lookup (gimp_thumb_png_name (uri), NULL, size);
 
440
 
 
441
  if (! result)
 
442
    {
 
443
      gchar *filename = _gimp_thumb_filename_from_uri (uri);
 
444
 
 
445
      if (filename)
 
446
        {
 
447
          const gchar *baseuri = strrchr (uri, '/');
 
448
 
 
449
          if (baseuri && baseuri[0] && baseuri[1])
 
450
            {
 
451
              gchar *dirname = g_path_get_dirname (filename);
 
452
 
 
453
              result = gimp_thumb_png_lookup (gimp_thumb_png_name (baseuri + 1),
 
454
                                              dirname, size);
 
455
 
 
456
              g_free (dirname);
 
457
            }
 
458
 
 
459
          g_free (filename);
 
460
        }
 
461
    }
 
462
 
 
463
  return result;
 
464
}
 
465
 
 
466
/**
 
467
 * gimp_thumb_file_test:
 
468
 * @filename: a filename in the encoding of the filesystem
 
469
 * @mtime: return location for modification time
 
470
 * @size: return location for file size
 
471
 * @err_no: return location for system "errno"
 
472
 *
 
473
 * This is a convenience and portability wrapper around stat(). It
 
474
 * checks if the given @filename exists and returns modification time
 
475
 * and file size in 64bit integer values.
 
476
 *
 
477
 * Return value: The type of the file, or #GIMP_THUMB_FILE_TYPE_NONE if
 
478
 *               the file doesn't exist.
 
479
 **/
 
480
GimpThumbFileType
 
481
gimp_thumb_file_test (const gchar *filename,
 
482
                      gint64      *mtime,
 
483
                      gint64      *size,
 
484
                      gint        *err_no)
 
485
{
 
486
  struct stat s;
 
487
 
 
488
  g_return_val_if_fail (filename != NULL, FALSE);
 
489
 
 
490
  if (stat (filename, &s) == 0)
 
491
    {
 
492
      if (mtime)  *mtime  = s.st_mtime;
 
493
      if (size)   *size   = s.st_size;
 
494
      if (err_no) *err_no = 0;
 
495
 
 
496
      if (S_ISREG (s.st_mode))
 
497
        {
 
498
          return GIMP_THUMB_FILE_TYPE_REGULAR;
 
499
        }
 
500
      else if (S_ISDIR (s.st_mode))
 
501
        {
 
502
          return GIMP_THUMB_FILE_TYPE_FOLDER;
 
503
        }
 
504
 
 
505
      return GIMP_THUMB_FILE_TYPE_SPECIAL;
 
506
    }
 
507
 
 
508
  if (mtime)  *mtime  = 0;
 
509
  if (size)   *size   = 0;
 
510
  if (err_no) *err_no = errno;
 
511
 
 
512
  return GIMP_THUMB_FILE_TYPE_NONE;
 
513
}
 
514
 
 
515
/**
 
516
 * gimp_thumbs_delete_for_uri:
 
517
 * @uri: an escaped URI
 
518
 *
 
519
 * Deletes all thumbnails for the image file specified by @uri from the
 
520
 * user's thumbnail repository.
 
521
 *
 
522
 * Since: GIMP 2.2
 
523
 **/
 
524
void
 
525
gimp_thumbs_delete_for_uri (const gchar *uri)
 
526
{
 
527
  gint i;
 
528
 
 
529
  g_return_if_fail (gimp_thumb_initialized);
 
530
  g_return_if_fail (uri != NULL);
 
531
 
 
532
  for (i = 0; i < thumb_num_sizes; i++)
 
533
    {
 
534
      gchar *filename = gimp_thumb_name_from_uri (uri, thumb_sizes[i]);
 
535
 
 
536
      if (filename)
 
537
        {
 
538
          unlink (filename);
 
539
          g_free (filename);
 
540
        }
 
541
    }
 
542
}
 
543
 
 
544
/**
 
545
 * gimp_thumbs_delete_for_uri_local:
 
546
 * @uri: an escaped URI
 
547
 *
 
548
 * Deletes all thumbnails for the image file specified by @uri from
 
549
 * the local thumbnail repository.
 
550
 *
 
551
 * Since: GIMP 2.2
 
552
 **/
 
553
void
 
554
gimp_thumbs_delete_for_uri_local (const gchar *uri)
 
555
{
 
556
  gint i;
 
557
 
 
558
  g_return_if_fail (gimp_thumb_initialized);
 
559
  g_return_if_fail (uri != NULL);
 
560
 
 
561
  for (i = 0; i < thumb_num_sizes; i++)
 
562
    {
 
563
      gchar *filename = gimp_thumb_name_from_uri_local (uri, thumb_sizes[i]);
 
564
 
 
565
      if (filename)
 
566
        {
 
567
          unlink (filename);
 
568
          g_free (filename);
 
569
        }
 
570
    }
 
571
}
 
572
 
 
573
void
 
574
_gimp_thumbs_delete_others (const gchar   *uri,
 
575
                            GimpThumbSize  size)
 
576
{
 
577
  gint i;
 
578
 
 
579
  g_return_if_fail (gimp_thumb_initialized);
 
580
  g_return_if_fail (uri != NULL);
 
581
 
 
582
  size = gimp_thumb_size (size);
 
583
 
 
584
  for (i = 0; i < thumb_num_sizes; i++)
 
585
    {
 
586
      gchar *filename;
 
587
 
 
588
      if (i == size)
 
589
        continue;
 
590
 
 
591
      filename = gimp_thumb_name_from_uri (uri, thumb_sizes[i]);
 
592
      if (filename)
 
593
        {
 
594
          unlink (filename);
 
595
          g_free (filename);
 
596
        }
 
597
    }
 
598
}
 
599
 
 
600
gchar *
 
601
_gimp_thumb_filename_from_uri (const gchar *uri)
 
602
{
 
603
  gchar *filename;
 
604
  gchar *hostname;
 
605
 
 
606
  g_return_val_if_fail (uri != NULL, NULL);
 
607
 
 
608
  filename = g_filename_from_uri (uri, &hostname, NULL);
 
609
 
 
610
  if (!filename)
 
611
    return NULL;
 
612
 
 
613
  if (hostname)
 
614
    {
 
615
      /*  we have a file: URI with a hostname                           */
 
616
 
 
617
#ifdef G_OS_WIN32
 
618
      /*  on Win32, create a valid UNC path and use it as the filename  */
 
619
      gchar *tmp = g_build_filename ("//", hostname, filename, NULL);
 
620
 
 
621
      g_free (filename);
 
622
      filename = tmp;
 
623
#else
 
624
      /*  otherwise return NULL, caller should use URI then             */
 
625
      g_free (filename);
 
626
      filename = NULL;
 
627
#endif
 
628
 
 
629
      g_free (hostname);
 
630
    }
 
631
 
 
632
  return filename;
 
633
}
 
634
 
 
635
static void
 
636
gimp_thumb_exit (void)
 
637
{
 
638
  gint i;
 
639
 
 
640
  g_free (thumb_dir);
 
641
  g_free (thumb_sizes);
 
642
  g_free (thumb_sizenames);
 
643
  for (i = 0; i < thumb_num_sizes; i++)
 
644
    g_free (thumb_subdirs[i]);
 
645
  g_free (thumb_subdirs);
 
646
  g_free (thumb_fail_subdir);
 
647
 
 
648
  thumb_num_sizes        = 0;
 
649
  thumb_sizes            = NULL;
 
650
  thumb_sizenames        = NULL;
 
651
  thumb_dir              = NULL;
 
652
  thumb_subdirs          = NULL;
 
653
  thumb_fail_subdir      = NULL;
 
654
  gimp_thumb_initialized = FALSE;
 
655
}
 
656
 
 
657
static gint
 
658
gimp_thumb_size (GimpThumbSize size)
 
659
{
 
660
  gint i = 0;
 
661
 
 
662
  if (size > GIMP_THUMB_SIZE_FAIL)
 
663
    {
 
664
      for (i = 1;
 
665
           i < thumb_num_sizes && thumb_sizes[i] < size;
 
666
           i++)
 
667
        /* nothing */;
 
668
 
 
669
      if (i == thumb_num_sizes)
 
670
        i--;
 
671
    }
 
672
 
 
673
  return i;
 
674
}
 
675
 
 
676
static gchar *
 
677
gimp_thumb_png_lookup (const gchar   *name,
 
678
                       const gchar   *basedir,
 
679
                       GimpThumbSize *size)
 
680
{
 
681
  gchar  *thumb_name = NULL;
 
682
  gchar **subdirs    = NULL;
 
683
  gint    i, n;
 
684
 
 
685
  if (basedir)
 
686
    {
 
687
      gchar *dir = g_build_filename (basedir, ".thumblocal", NULL);
 
688
 
 
689
      if (g_file_test (basedir, G_FILE_TEST_IS_DIR))
 
690
        {
 
691
          gint i;
 
692
 
 
693
          subdirs = g_new (gchar *, thumb_num_sizes);
 
694
 
 
695
          subdirs[0] = NULL;  /*  GIMP_THUMB_SIZE_FAIL  */
 
696
 
 
697
          for (i = 1; i < thumb_num_sizes; i++)
 
698
            subdirs[i] = g_build_filename (dir, thumb_sizenames[i], NULL);
 
699
        }
 
700
 
 
701
      g_free (dir);
 
702
    }
 
703
  else
 
704
    {
 
705
      subdirs = thumb_subdirs;
 
706
    }
 
707
 
 
708
  if (! subdirs)
 
709
    return NULL;
 
710
 
 
711
  i = n = gimp_thumb_size (*size);
 
712
 
 
713
  for (; i < thumb_num_sizes; i++)
 
714
    {
 
715
      if (! subdirs[i])
 
716
        continue;
 
717
 
 
718
      thumb_name = g_build_filename (subdirs[i], name, NULL);
 
719
 
 
720
      if (gimp_thumb_file_test (thumb_name,
 
721
                                NULL, NULL,
 
722
                                NULL) == GIMP_THUMB_FILE_TYPE_REGULAR)
 
723
        {
 
724
          *size = thumb_sizes[i];
 
725
          goto finish;
 
726
        }
 
727
 
 
728
      g_free (thumb_name);
 
729
    }
 
730
 
 
731
  for (i = n - 1; i >= 0; i--)
 
732
    {
 
733
      if (! subdirs[i])
 
734
        continue;
 
735
 
 
736
      thumb_name = g_build_filename (subdirs[i], name, NULL);
 
737
 
 
738
      if (gimp_thumb_file_test (thumb_name,
 
739
                                NULL, NULL,
 
740
                                NULL) == GIMP_THUMB_FILE_TYPE_REGULAR)
 
741
        {
 
742
          *size = thumb_sizes[i];
 
743
          goto finish;
 
744
        }
 
745
 
 
746
      g_free (thumb_name);
 
747
    }
 
748
 
 
749
  thumb_name = NULL;
 
750
 
 
751
 finish:
 
752
  if (basedir)
 
753
    {
 
754
      for (i = 0; i < thumb_num_sizes; i++)
 
755
        g_free (subdirs[i]);
 
756
      g_free (subdirs);
 
757
    }
 
758
 
 
759
  return thumb_name;
 
760
}
 
761
 
 
762
static const gchar *
 
763
gimp_thumb_png_name (const gchar *uri)
 
764
{
 
765
  static gchar name[40];
 
766
  guchar       digest[16];
 
767
  guchar       n;
 
768
  gint         i;
 
769
 
 
770
  gimp_md5_get_digest (uri, -1, digest);
 
771
 
 
772
  for (i = 0; i < 16; i++)
 
773
    {
 
774
      n = (digest[i] >> 4) & 0xF;
 
775
      name[i * 2]     = (n > 9) ? 'a' + n - 10 : '0' + n;
 
776
 
 
777
      n = digest[i] & 0xF;
 
778
      name[i * 2 + 1] = (n > 9) ? 'a' + n - 10 : '0' + n;
 
779
    }
 
780
 
 
781
  strncpy (name + 32, ".png", 5);
 
782
 
 
783
  return (const gchar *) name;
 
784
}