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

« back to all changes in this revision

Viewing changes to plug-ins/common/url.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
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
 
/* Author: Josh MacDonald. */
20
 
 
21
 
#include "config.h"
22
 
 
23
 
#include <stdlib.h>
24
 
#include <stdio.h>
25
 
#include <string.h>
26
 
#include <errno.h>
27
 
#include <sys/param.h>
28
 
#include <sys/wait.h>
29
 
 
30
 
#ifdef HAVE_UNISTD_H
31
 
#include <unistd.h>
32
 
#endif
33
 
 
34
 
#include <libgimp/gimp.h>
35
 
#include <libgimp/gimpui.h>
36
 
 
37
 
#include "libgimp/stdplugins-intl.h"
38
 
 
39
 
 
40
 
#define TIMEOUT "300"
41
 
#define BUFSIZE 1024
42
 
 
43
 
static void    query (void);
44
 
static void    run   (const gchar      *name,
45
 
                      gint              nparams,
46
 
                      const GimpParam  *param,
47
 
                      gint             *nreturn_vals,
48
 
                      GimpParam       **return_vals);
49
 
 
50
 
static gint32  load_image (const gchar       *filename,
51
 
                           GimpRunMode        run_mode,
52
 
                           GimpPDBStatusType *status /* return value */);
53
 
 
54
 
GimpPlugInInfo PLUG_IN_INFO =
55
 
{
56
 
  NULL,  /* init_proc  */
57
 
  NULL,  /* quit_proc  */
58
 
  query, /* query_proc */
59
 
  run,   /* run_proc   */
60
 
};
61
 
 
62
 
MAIN ()
63
 
 
64
 
static void
65
 
query (void)
66
 
{
67
 
  static GimpParamDef load_args[] =
68
 
  {
69
 
    { GIMP_PDB_INT32,  "run_mode",     "Interactive, non-interactive" },
70
 
    { GIMP_PDB_STRING, "filename",     "The name of the file to load" },
71
 
    { GIMP_PDB_STRING, "raw_filename", "The name entered" }
72
 
  };
73
 
 
74
 
  static GimpParamDef load_return_vals[] =
75
 
  {
76
 
    { GIMP_PDB_IMAGE, "image", "Output image" }
77
 
  };
78
 
 
79
 
  gimp_install_procedure ("file_url_load",
80
 
                          "loads files given a URL",
81
 
                          "You need to have GNU Wget installed.",
82
 
                          "Spencer Kimball & Peter Mattis",
83
 
                          "Spencer Kimball & Peter Mattis",
84
 
                          "1995-1997",
85
 
                          N_("URL"),
86
 
                          NULL,
87
 
                          GIMP_PLUGIN,
88
 
                          G_N_ELEMENTS (load_args),
89
 
                          G_N_ELEMENTS (load_return_vals),
90
 
                          load_args, load_return_vals);
91
 
 
92
 
  gimp_plugin_icon_register ("file_url_load",
93
 
                             GIMP_ICON_TYPE_STOCK_ID, GIMP_STOCK_WEB);
94
 
  gimp_register_load_handler ("file_url_load",
95
 
                              "",
96
 
                              "http:,https:,ftp:");
97
 
}
98
 
 
99
 
static void
100
 
run (const gchar      *name,
101
 
     gint              nparams,
102
 
     const GimpParam  *param,
103
 
     gint             *nreturn_vals,
104
 
     GimpParam       **return_vals)
105
 
{
106
 
  static GimpParam  values[2];
107
 
  GimpRunMode       run_mode;
108
 
  GimpPDBStatusType status = GIMP_PDB_SUCCESS;
109
 
  gint32            image_ID;
110
 
 
111
 
  run_mode = param[0].data.d_int32;
112
 
 
113
 
  *nreturn_vals = 1;
114
 
  *return_vals  = values;
115
 
  values[0].type          = GIMP_PDB_STATUS;
116
 
  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
117
 
 
118
 
  if (strcmp (name, "file_url_load") == 0)
119
 
    {
120
 
      image_ID = load_image (param[2].data.d_string, run_mode, &status);
121
 
 
122
 
      if (image_ID != -1 &&
123
 
          status == GIMP_PDB_SUCCESS)
124
 
        {
125
 
          *nreturn_vals = 2;
126
 
          values[1].type         = GIMP_PDB_IMAGE;
127
 
          values[1].data.d_image = image_ID;
128
 
        }
129
 
    }
130
 
  else
131
 
    {
132
 
      status = GIMP_PDB_CALLING_ERROR;
133
 
    }
134
 
 
135
 
  values[0].data.d_status = status;
136
 
}
137
 
 
138
 
static gint32
139
 
load_image (const gchar       *filename,
140
 
            GimpRunMode        run_mode,
141
 
            GimpPDBStatusType *status)
142
 
{
143
 
  gint32    image_ID;
144
 
  gchar    *ext = strrchr (filename, '.');
145
 
  gchar    *tmpname;
146
 
  gint      pid;
147
 
  gint      p[2];
148
 
  gboolean  name_image = FALSE;
149
 
 
150
 
  if (!ext || ext[1] == 0 || strchr (ext, '/'))
151
 
    {
152
 
      tmpname = gimp_temp_name ("xxx");
153
 
    }
154
 
  else
155
 
    {
156
 
      tmpname = gimp_temp_name (ext + 1);
157
 
      name_image = TRUE;
158
 
    }
159
 
 
160
 
  if (pipe (p) != 0)
161
 
    {
162
 
      g_message ("pipe() failed: %s", g_strerror (errno));
163
 
      g_free (tmpname);
164
 
      *status = GIMP_PDB_EXECUTION_ERROR;
165
 
      return -1;
166
 
    }
167
 
 
168
 
  if ((pid = fork()) < 0)
169
 
    {
170
 
      g_message ("fork() failed: %s", g_strerror (errno));
171
 
      g_free (tmpname);
172
 
      *status = GIMP_PDB_EXECUTION_ERROR;
173
 
      return -1;
174
 
    }
175
 
  else if (pid == 0)
176
 
    {
177
 
      close (p[0]);
178
 
      close (2);
179
 
      dup (p[1]);
180
 
      close (p[1]);
181
 
 
182
 
#ifdef HAVE_PUTENV
183
 
      /* produce deterministic output */
184
 
      putenv ("LANGUAGE=C");
185
 
      putenv ("LC_ALL=C");
186
 
      putenv ("LANG=C");
187
 
#endif
188
 
 
189
 
      execlp ("wget",
190
 
              "wget", "-v", "-e", "server-response=off", "-T", TIMEOUT,
191
 
              filename, "-O", tmpname, NULL);
192
 
      g_message ("exec() failed: wget: %s", g_strerror (errno));
193
 
      g_free (tmpname);
194
 
      _exit (127);
195
 
    }
196
 
  else
197
 
    {
198
 
      FILE     *input;
199
 
      gchar     buf[BUFSIZE];
200
 
      gboolean  seen_resolve = FALSE;
201
 
      gboolean  connected = FALSE;
202
 
      gboolean  redirect = FALSE;
203
 
      gboolean  file_found = FALSE;
204
 
      gchar     sizestr[32];
205
 
      gint      size = 0;
206
 
      gchar    *size_msg;
207
 
      gchar    *message;
208
 
      gint      i, j;
209
 
      gchar     dot;
210
 
      gint      kilobytes = 0;
211
 
      gboolean  finished = FALSE;
212
 
 
213
 
      gboolean  debug = FALSE;
214
 
 
215
 
#define DEBUG(x) if (debug) g_printerr (x)
216
 
 
217
 
      close (p[1]);
218
 
 
219
 
      input = fdopen (p[0], "r");
220
 
 
221
 
      /*  hardcoded and not-really-foolproof scanning of wget putput  */
222
 
 
223
 
    wget_begin:
224
 
      /*  Eat any Location lines */
225
 
      if (redirect && fgets (buf, BUFSIZE, input) == NULL)
226
 
        {
227
 
          g_message ("wget exited abnormally on URL '%s'", filename);
228
 
          g_free (tmpname);
229
 
          *status = GIMP_PDB_EXECUTION_ERROR;
230
 
          return -1;
231
 
        }
232
 
 
233
 
      redirect = FALSE;
234
 
 
235
 
      if (fgets (buf, BUFSIZE, input) == NULL)
236
 
        {
237
 
          /*  no message here because failing on the first line means
238
 
           *  that wget was not found
239
 
           */
240
 
          g_free (tmpname);
241
 
          *status = GIMP_PDB_EXECUTION_ERROR;
242
 
          return -1;
243
 
        }
244
 
 
245
 
      DEBUG (buf);
246
 
 
247
 
      /*  The second line is the local copy of the file  */
248
 
      if (fgets (buf, BUFSIZE, input) == NULL)
249
 
        {
250
 
          g_message ("wget exited abnormally on URL '%s'", filename);
251
 
          g_free (tmpname);
252
 
          *status = GIMP_PDB_EXECUTION_ERROR;
253
 
          return -1;
254
 
        }
255
 
 
256
 
      DEBUG (buf);
257
 
 
258
 
      /*  The third line is "Connecting to..."  */
259
 
      gimp_progress_init ("Connecting to server... "
260
 
                          "(timeout is "TIMEOUT" seconds)");
261
 
 
262
 
    read_connect:
263
 
      if (fgets (buf, BUFSIZE, input) == NULL)
264
 
        {
265
 
          g_message ("wget exited abnormally on URL '%s'", filename);
266
 
          g_free (tmpname);
267
 
          *status = GIMP_PDB_EXECUTION_ERROR;
268
 
          return -1;
269
 
        }
270
 
      else if (strstr (buf, "connected"))
271
 
        {
272
 
          connected = TRUE;
273
 
        }
274
 
      /* newer wgets have a "Resolving foo" line, so eat it */
275
 
      else if (!seen_resolve && strstr (buf, "Resolving"))
276
 
        {
277
 
          seen_resolve = TRUE;
278
 
          goto read_connect;
279
 
        }
280
 
 
281
 
      DEBUG (buf);
282
 
 
283
 
      /*  The fourth line is either the network request or an error  */
284
 
      gimp_progress_init ("Opening URL... "
285
 
                          "(timeout is "TIMEOUT" seconds)");
286
 
 
287
 
      if (fgets (buf, BUFSIZE, input) == NULL)
288
 
        {
289
 
          g_message ("wget exited abnormally on URL '%s'", filename);
290
 
          g_free (tmpname);
291
 
          *status = GIMP_PDB_EXECUTION_ERROR;
292
 
          return -1;
293
 
        }
294
 
      else if (! connected)
295
 
        {
296
 
          g_message ("A network error occured: %s", buf);
297
 
 
298
 
          DEBUG (buf);
299
 
 
300
 
          g_free (tmpname);
301
 
          *status = GIMP_PDB_EXECUTION_ERROR;
302
 
          return -1;
303
 
        }
304
 
      else if (strstr (buf, "302 Found"))
305
 
        {
306
 
          DEBUG (buf);
307
 
 
308
 
          connected = FALSE;
309
 
          seen_resolve = FALSE;
310
 
 
311
 
          redirect = TRUE;
312
 
          goto wget_begin;
313
 
        }
314
 
 
315
 
      DEBUG (buf);
316
 
 
317
 
      /*  The fifth line is either the length of the file or an error  */
318
 
      if (fgets (buf, BUFSIZE, input) == NULL)
319
 
        {
320
 
          g_message ("wget exited abnormally on URL '%s'", filename);
321
 
          g_free (tmpname);
322
 
          *status = GIMP_PDB_EXECUTION_ERROR;
323
 
          return -1;
324
 
        }
325
 
      else if (strstr (buf, "Length"))
326
 
        {
327
 
          file_found = TRUE;
328
 
        }
329
 
      else
330
 
        {
331
 
          g_message ("A network error occured: %s", buf);
332
 
 
333
 
          DEBUG (buf);
334
 
 
335
 
          g_free (tmpname);
336
 
          *status = GIMP_PDB_EXECUTION_ERROR;
337
 
          return -1;
338
 
        }
339
 
 
340
 
      DEBUG (buf);
341
 
 
342
 
      if (sscanf (buf, "Length: %31s", sizestr) != 1)
343
 
        {
344
 
          g_message ("Could not parse wget's file length message");
345
 
          g_free (tmpname);
346
 
          *status = GIMP_PDB_EXECUTION_ERROR;
347
 
          return -1;
348
 
        }
349
 
 
350
 
      /*  strip away commas  */
351
 
      for (i = 0, j = 0; i < sizeof (sizestr); i++, j++)
352
 
        {
353
 
          if (sizestr[i] == ',')
354
 
            i++;
355
 
 
356
 
          sizestr[j] = sizestr[i];
357
 
 
358
 
          if (sizestr[j] == '\0')
359
 
            break;
360
 
        }
361
 
 
362
 
      size = atoi (sizestr);
363
 
 
364
 
      if (size > 0)
365
 
        size_msg = g_strdup_printf ("%d bytes", size);
366
 
      else
367
 
        size_msg = g_strdup ("unknown amount");
368
 
 
369
 
      /*  Start the actual download...  */
370
 
      message = g_strdup_printf ("Downloading %s of image data... "
371
 
                                 "(timeout is "TIMEOUT" seconds)", size_msg);
372
 
      gimp_progress_init (message);
373
 
      g_free (message);
374
 
      g_free (size_msg);
375
 
 
376
 
      /*  Switch to byte parsing wget's output...  */
377
 
 
378
 
      while (1)
379
 
        {
380
 
          dot = fgetc (input);
381
 
 
382
 
          if (feof (input))
383
 
            break;
384
 
 
385
 
          if (debug)
386
 
            {
387
 
              fputc (dot, stderr);
388
 
              fflush (stderr);
389
 
            }
390
 
 
391
 
          if (dot == '.')  /* one kilobyte */
392
 
            {
393
 
              kilobytes++;
394
 
 
395
 
              if (size > 0)
396
 
                gimp_progress_update ((gdouble) (kilobytes * 1024) /
397
 
                                      (gdouble) size);
398
 
            }
399
 
          else if (dot == ':')  /* the time string contains a ':' */
400
 
            {
401
 
              fgets (buf, BUFSIZE, input);
402
 
 
403
 
              DEBUG (buf);
404
 
 
405
 
              if (! strstr (buf, "error"))
406
 
                {
407
 
                  finished = TRUE;
408
 
                  gimp_progress_update (1.0);
409
 
                }
410
 
 
411
 
              break;
412
 
            }
413
 
        }
414
 
 
415
 
      if (! finished)
416
 
        {
417
 
          g_message ("wget exited before finishing downloading URL\n'%s'",
418
 
                     filename);
419
 
          unlink (tmpname);
420
 
          g_free (tmpname);
421
 
          *status = GIMP_PDB_EXECUTION_ERROR;
422
 
          return -1;
423
 
        }
424
 
    }
425
 
 
426
 
  image_ID = gimp_file_load (run_mode, tmpname, tmpname);
427
 
 
428
 
  unlink (tmpname);
429
 
  g_free (tmpname);
430
 
 
431
 
  if (image_ID != -1)
432
 
    {
433
 
      *status = GIMP_PDB_SUCCESS;
434
 
      if (name_image)
435
 
        gimp_image_set_filename (image_ID, filename);
436
 
      else
437
 
        gimp_image_set_filename (image_ID, "");
438
 
    }
439
 
  else
440
 
    *status = GIMP_PDB_EXECUTION_ERROR;
441
 
 
442
 
  return image_ID;
443
 
}