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

« back to all changes in this revision

Viewing changes to plug-ins/uri/uri-backend-gnomevfs.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: james.westby@ubuntu.com-20070502163303-6wchheivjxgjtlna
Tags: upstream-2.3.16
ImportĀ upstreamĀ versionĀ 2.3.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GIMP - The GNU Image Manipulation Program
 
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
17
 */
 
18
 
 
19
#include "config.h"
 
20
 
 
21
#include <libgnomevfs/gnome-vfs.h>
 
22
 
 
23
#ifdef HAVE_GNOMEUI
 
24
#include <libgnomeui/gnome-authentication-manager.h>
 
25
#endif
 
26
#ifdef HAVE_GNOME_KEYRING
 
27
#include <gnome-keyring.h>
 
28
#endif
 
29
 
 
30
#include <libgimp/gimp.h>
 
31
#include <libgimp/gimpui.h>
 
32
 
 
33
#include "uri-backend.h"
 
34
 
 
35
#include "libgimp/stdplugins-intl.h"
 
36
 
 
37
 
 
38
#define BUFSIZE 4096
 
39
 
 
40
 
 
41
/*  local function prototypes  */
 
42
 
 
43
static gchar    * get_protocols (void);
 
44
static gboolean   copy_uri      (const gchar  *src_uri,
 
45
                                 const gchar  *dest_uri,
 
46
                                 const gchar  *copying_format_str,
 
47
                                 const gchar  *copied_format_str,
 
48
                                 GError      **error);
 
49
 
 
50
#ifdef HAVE_GNOME_KEYRING
 
51
static void vfs_async_fill_authentication_callback (gconstpointer in,
 
52
                                                    size_t        in_size,
 
53
                                                    gpointer      out,
 
54
                                                    size_t        out_size,
 
55
                                                    gpointer      user_data,
 
56
                                                    GnomeVFSModuleCallbackResponse response,
 
57
                                                    gpointer      response_data);
 
58
static void vfs_fill_authentication_callback       (gconstpointer in,
 
59
                                                    size_t        in_size,
 
60
                                                    gpointer      out,
 
61
                                                    size_t        out_size,
 
62
                                                    gpointer      user_data);
 
63
#endif /* HAVE_GNOME_KEYRING */
 
64
 
 
65
 
 
66
/*  private variables  */
 
67
 
 
68
static gchar *supported_protocols = NULL;
 
69
 
 
70
 
 
71
/*  public functions  */
 
72
 
 
73
gboolean
 
74
uri_backend_init (const gchar  *plugin_name,
 
75
                  gboolean      run,
 
76
                  GimpRunMode   run_mode,
 
77
                  GError      **error)
 
78
{
 
79
  if (! gnome_vfs_init ())
 
80
    {
 
81
      g_set_error (error, 0, 0, "Could not initialize GnomeVFS");
 
82
      return FALSE;
 
83
    }
 
84
 
 
85
#ifdef HAVE_GNOMEUI
 
86
  if (run)
 
87
    {
 
88
      if (run_mode == GIMP_RUN_INTERACTIVE)
 
89
        {
 
90
          gimp_ui_init (plugin_name, FALSE);
 
91
          gnome_authentication_manager_init ();
 
92
        }
 
93
      else
 
94
        {
 
95
#ifdef HAVE_GNOME_KEYRING
 
96
          gnome_vfs_async_module_callback_set_default
 
97
            (GNOME_VFS_MODULE_CALLBACK_FILL_AUTHENTICATION,
 
98
             vfs_async_fill_authentication_callback,
 
99
             GINT_TO_POINTER (0),
 
100
             NULL);
 
101
 
 
102
          gnome_vfs_module_callback_set_default
 
103
            (GNOME_VFS_MODULE_CALLBACK_FILL_AUTHENTICATION,
 
104
             vfs_fill_authentication_callback,
 
105
             GINT_TO_POINTER (0),
 
106
             NULL);
 
107
#endif /* HAVE_GNOME_KEYRING */
 
108
        }
 
109
    }
 
110
#endif /* HAVE_GNOMEUI */
 
111
 
 
112
  return TRUE;
 
113
}
 
114
 
 
115
void
 
116
uri_backend_shutdown (void)
 
117
{
 
118
  gnome_vfs_shutdown ();
 
119
}
 
120
 
 
121
const gchar *
 
122
uri_backend_get_load_protocols (void)
 
123
{
 
124
  if (! supported_protocols)
 
125
    supported_protocols = get_protocols ();
 
126
 
 
127
  return supported_protocols;
 
128
}
 
129
 
 
130
const gchar *
 
131
uri_backend_get_save_protocols (void)
 
132
{
 
133
  if (! supported_protocols)
 
134
    supported_protocols = get_protocols ();
 
135
 
 
136
  return supported_protocols;
 
137
}
 
138
 
 
139
gboolean
 
140
uri_backend_load_image (const gchar  *uri,
 
141
                        const gchar  *tmpname,
 
142
                        GimpRunMode   run_mode,
 
143
                        GError      **error)
 
144
{
 
145
  gchar    *dest_uri;
 
146
  gboolean  success;
 
147
 
 
148
  dest_uri = g_filename_to_uri (tmpname, NULL, NULL);
 
149
  success = copy_uri (uri, dest_uri,
 
150
                      _("Downloading %s of image data..."),
 
151
                      _("Downloaded %s of image data"),
 
152
                      error);
 
153
  g_free (dest_uri);
 
154
 
 
155
  return success;
 
156
}
 
157
 
 
158
gboolean
 
159
uri_backend_save_image (const gchar  *uri,
 
160
                        const gchar  *tmpname,
 
161
                        GimpRunMode   run_mode,
 
162
                        GError      **error)
 
163
{
 
164
  gchar    *src_uri;
 
165
  gboolean  success;
 
166
 
 
167
  src_uri = g_filename_to_uri (tmpname, NULL, NULL);
 
168
  success = copy_uri (src_uri, uri,
 
169
                      _("Uploading %s of image data..."),
 
170
                      _("Uploaded %s of image data"),
 
171
                      error);
 
172
  g_free (src_uri);
 
173
 
 
174
  return success;
 
175
}
 
176
 
 
177
 
 
178
/*  private functions  */
 
179
 
 
180
static gchar *
 
181
get_protocols (void)
 
182
{
 
183
  static const gchar *protocols[] =
 
184
  {
 
185
    "http:",
 
186
    "https:",
 
187
    "ftp:",
 
188
    "sftp:",
 
189
    "ssh:",
 
190
    "smb:",
 
191
    "dav:",
 
192
    "davs:"
 
193
  };
 
194
 
 
195
  GString *string = g_string_new (NULL);
 
196
  gint     i;
 
197
 
 
198
  for (i = 0; i < G_N_ELEMENTS (protocols); i++)
 
199
    {
 
200
      gchar       *uri;
 
201
      GnomeVFSURI *vfs_uri;
 
202
 
 
203
      uri = g_strdup_printf ("%s//foo/bar.xcf", protocols[i]);
 
204
 
 
205
      vfs_uri = gnome_vfs_uri_new (uri);
 
206
 
 
207
      if (vfs_uri)
 
208
        {
 
209
          if (string->len > 0)
 
210
            g_string_append_c (string, ',');
 
211
 
 
212
          g_string_append (string, protocols[i]);
 
213
 
 
214
          gnome_vfs_uri_unref (vfs_uri);
 
215
        }
 
216
 
 
217
      g_free (uri);
 
218
    }
 
219
 
 
220
  return g_string_free (string, FALSE);
 
221
}
 
222
 
 
223
static gboolean
 
224
copy_uri (const gchar  *src_uri,
 
225
          const gchar  *dest_uri,
 
226
          const gchar  *copying_format_str,
 
227
          const gchar  *copied_format_str,
 
228
          GError      **error)
 
229
{
 
230
  GnomeVFSHandle   *read_handle;
 
231
  GnomeVFSHandle   *write_handle;
 
232
  GnomeVFSFileInfo *src_info;
 
233
  GnomeVFSFileSize  file_size  = 0;
 
234
  GnomeVFSFileSize  bytes_read = 0;
 
235
  guchar            buffer[BUFSIZE];
 
236
  GnomeVFSResult    result;
 
237
  gchar            *memsize;
 
238
  GTimeVal          last_time = { 0, 0 };
 
239
 
 
240
  gimp_progress_init (_("Connecting to server"));
 
241
 
 
242
  src_info = gnome_vfs_file_info_new ();
 
243
  result = gnome_vfs_get_file_info (src_uri, src_info, 0);
 
244
 
 
245
  /*  ignore errors here, they will be noticed below  */
 
246
  if (result == GNOME_VFS_OK &&
 
247
      (src_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE))
 
248
    {
 
249
      file_size = src_info->size;
 
250
    }
 
251
 
 
252
  gnome_vfs_file_info_unref (src_info);
 
253
 
 
254
  result = gnome_vfs_open (&read_handle, src_uri, GNOME_VFS_OPEN_READ);
 
255
 
 
256
  if (result != GNOME_VFS_OK)
 
257
    {
 
258
      g_set_error (error, 0, 0,
 
259
                   _("Could not open '%s' for reading: %s"),
 
260
                   src_uri, gnome_vfs_result_to_string (result));
 
261
      return FALSE;
 
262
    }
 
263
 
 
264
  result = gnome_vfs_create (&write_handle, dest_uri,
 
265
                             GNOME_VFS_OPEN_WRITE, FALSE, 0644);
 
266
 
 
267
  if (result != GNOME_VFS_OK)
 
268
    {
 
269
      g_set_error (error, 0, 0,
 
270
                   _("Could not open '%s' for writing: %s"),
 
271
                   dest_uri, gnome_vfs_result_to_string (result));
 
272
      gnome_vfs_close (read_handle);
 
273
      return FALSE;
 
274
    }
 
275
 
 
276
  memsize = gimp_memsize_to_string (file_size);
 
277
 
 
278
  gimp_progress_init_printf (file_size > 0 ?
 
279
                             copying_format_str : copied_format_str,
 
280
                             memsize);
 
281
 
 
282
  g_free (memsize);
 
283
 
 
284
  while (TRUE)
 
285
    {
 
286
      GnomeVFSFileSize  chunk_read;
 
287
      GnomeVFSFileSize  chunk_written;
 
288
      GTimeVal          now;
 
289
 
 
290
      result = gnome_vfs_read (read_handle, buffer, sizeof (buffer),
 
291
                               &chunk_read);
 
292
 
 
293
      if (chunk_read == 0)
 
294
        {
 
295
          if (result != GNOME_VFS_ERROR_EOF)
 
296
            {
 
297
              memsize = gimp_memsize_to_string (sizeof (buffer));
 
298
              g_set_error (error, 0, 0,
 
299
                           _("Failed to read %s from '%s': %s"),
 
300
                           memsize, src_uri,
 
301
                           gnome_vfs_result_to_string (result));
 
302
              g_free (memsize);
 
303
 
 
304
              gnome_vfs_close (read_handle);
 
305
              gnome_vfs_close (write_handle);
 
306
              return FALSE;
 
307
            }
 
308
          else
 
309
            {
 
310
              gimp_progress_update (1.0);
 
311
              break;
 
312
            }
 
313
        }
 
314
 
 
315
      bytes_read += chunk_read;
 
316
 
 
317
      /*  update the progress only up to 10 times a second  */
 
318
 
 
319
      g_get_current_time (&now);
 
320
 
 
321
      if (((now.tv_sec - last_time.tv_sec) * 1000 +
 
322
           (now.tv_usec - last_time.tv_usec) / 1000) > 100)
 
323
        {
 
324
          if (file_size > 0)
 
325
            {
 
326
              gimp_progress_update ((gdouble) bytes_read / (gdouble) file_size);
 
327
            }
 
328
          else
 
329
            {
 
330
              memsize = gimp_memsize_to_string (bytes_read);
 
331
 
 
332
              gimp_progress_set_text_printf (copied_format_str, memsize);
 
333
              gimp_progress_pulse ();
 
334
 
 
335
              g_free (memsize);
 
336
            }
 
337
 
 
338
          last_time = now;
 
339
        }
 
340
 
 
341
      result = gnome_vfs_write (write_handle, buffer, chunk_read,
 
342
                                &chunk_written);
 
343
 
 
344
      if (chunk_written < chunk_read)
 
345
        {
 
346
          memsize = gimp_memsize_to_string (chunk_read);
 
347
          g_set_error (error, 0, 0,
 
348
                       _("Failed to write %s to '%s': %s"),
 
349
                       memsize, dest_uri,
 
350
                       gnome_vfs_result_to_string (result));
 
351
          g_free (memsize);
 
352
 
 
353
          gnome_vfs_close (read_handle);
 
354
          gnome_vfs_close (write_handle);
 
355
          return FALSE;
 
356
        }
 
357
    }
 
358
 
 
359
  gnome_vfs_close (read_handle);
 
360
  gnome_vfs_close (write_handle);
 
361
 
 
362
  return TRUE;
 
363
}
 
364
 
 
365
#ifdef HAVE_GNOME_KEYRING
 
366
 
 
367
/* gnome-keyring code copied from
 
368
 * libgnomeui/libgnomeui/gnome-authentication-manager.c CVS version 1.13
 
369
 */
 
370
 
 
371
typedef struct
 
372
{
 
373
  const GnomeVFSModuleCallbackFillAuthenticationIn *in_args;
 
374
  GnomeVFSModuleCallbackFillAuthenticationOut      *out_args;
 
375
 
 
376
  GnomeVFSModuleCallbackResponse                    response;
 
377
  gpointer                                          response_data;
 
378
} FillCallbackInfo;
 
379
 
 
380
static void
 
381
fill_auth_callback (GnomeKeyringResult result,
 
382
                    GList             *list,
 
383
                    gpointer           data)
 
384
{
 
385
  FillCallbackInfo                *info = data;
 
386
  GnomeKeyringNetworkPasswordData *pwd_data;;
 
387
 
 
388
  if (result != GNOME_KEYRING_RESULT_OK || list == NULL)
 
389
    {
 
390
      info->out_args->valid = FALSE;
 
391
    }
 
392
  else
 
393
    {
 
394
      /* We use the first result, which is the least specific match */
 
395
      pwd_data = list->data;
 
396
 
 
397
      info->out_args->valid    = TRUE;
 
398
      info->out_args->username = g_strdup (pwd_data->user);
 
399
      info->out_args->domain   = g_strdup (pwd_data->domain);
 
400
      info->out_args->password = g_strdup (pwd_data->password);
 
401
    }
 
402
 
 
403
  info->response (info->response_data);
 
404
}
 
405
 
 
406
static void /* GnomeVFSAsyncModuleCallback */
 
407
vfs_async_fill_authentication_callback (gconstpointer in,
 
408
                                        size_t in_size,
 
409
                                        gpointer out,
 
410
                                        size_t out_size,
 
411
                                        gpointer user_data,
 
412
                                        GnomeVFSModuleCallbackResponse response,
 
413
                                        gpointer response_data)
 
414
{
 
415
  GnomeVFSModuleCallbackFillAuthenticationIn  *in_real;
 
416
  GnomeVFSModuleCallbackFillAuthenticationOut *out_real;
 
417
  gpointer                                     request;
 
418
  FillCallbackInfo                            *info;
 
419
 
 
420
  g_return_if_fail
 
421
    (sizeof (GnomeVFSModuleCallbackFillAuthenticationIn) == in_size &&
 
422
     sizeof (GnomeVFSModuleCallbackFillAuthenticationOut) == out_size);
 
423
 
 
424
  g_return_if_fail (in != NULL);
 
425
  g_return_if_fail (out != NULL);
 
426
 
 
427
  in_real  = (GnomeVFSModuleCallbackFillAuthenticationIn *)in;
 
428
  out_real = (GnomeVFSModuleCallbackFillAuthenticationOut *)out;
 
429
 
 
430
  info = g_new (FillCallbackInfo, 1);
 
431
 
 
432
  info->in_args       = in_real;
 
433
  info->out_args      = out_real;
 
434
  info->response      = response;
 
435
  info->response_data = response_data;
 
436
 
 
437
  request = gnome_keyring_find_network_password (in_real->username,
 
438
                                                 in_real->domain,
 
439
                                                 in_real->server,
 
440
                                                 in_real->object,
 
441
                                                 in_real->protocol,
 
442
                                                 in_real->authtype,
 
443
                                                 in_real->port,
 
444
                                                 fill_auth_callback,
 
445
                                                 info, g_free);
 
446
}
 
447
 
 
448
static void /* GnomeVFSModuleCallback */
 
449
vfs_fill_authentication_callback (gconstpointer in,
 
450
                                  size_t        in_size,
 
451
                                  gpointer      out,
 
452
                                  size_t        out_size,
 
453
                                  gpointer      user_data)
 
454
{
 
455
  GnomeVFSModuleCallbackFillAuthenticationIn  *in_real;
 
456
  GnomeVFSModuleCallbackFillAuthenticationOut *out_real;
 
457
  GnomeKeyringNetworkPasswordData             *pwd_data;
 
458
  GList                                       *list;
 
459
  GnomeKeyringResult                           result;
 
460
 
 
461
  g_return_if_fail
 
462
    (sizeof (GnomeVFSModuleCallbackFillAuthenticationIn) == in_size &&
 
463
     sizeof (GnomeVFSModuleCallbackFillAuthenticationOut) == out_size);
 
464
 
 
465
  g_return_if_fail (in != NULL);
 
466
  g_return_if_fail (out != NULL);
 
467
 
 
468
  in_real  = (GnomeVFSModuleCallbackFillAuthenticationIn *)in;
 
469
  out_real = (GnomeVFSModuleCallbackFillAuthenticationOut *)out;
 
470
 
 
471
  result = gnome_keyring_find_network_password_sync (in_real->username,
 
472
                                                     in_real->domain,
 
473
                                                     in_real->server,
 
474
                                                     in_real->object,
 
475
                                                     in_real->protocol,
 
476
                                                     in_real->authtype,
 
477
                                                     in_real->port,
 
478
                                                     &list);
 
479
 
 
480
  if (result != GNOME_KEYRING_RESULT_OK || list == NULL)
 
481
    {
 
482
      out_real->valid = FALSE;
 
483
    }
 
484
  else
 
485
    {
 
486
      /* We use the first result, which is the least specific match */
 
487
      pwd_data = list->data;
 
488
 
 
489
      out_real->valid    = TRUE;
 
490
      out_real->username = g_strdup (pwd_data->user);
 
491
      out_real->domain   = g_strdup (pwd_data->domain);
 
492
      out_real->password = g_strdup (pwd_data->password);
 
493
 
 
494
      gnome_keyring_network_password_list_free (list);
 
495
    }
 
496
}
 
497
 
 
498
#endif /* HAVE_GNOME_KEYRING */