~ubuntu-branches/ubuntu/dapper/gnupg2/dapper

« back to all changes in this revision

Viewing changes to g10/photoid.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* photoid.c - photo ID handling code
 
2
 * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
 
3
 *
 
4
 * This file is part of GnuPG.
 
5
 *
 
6
 * GnuPG is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * GnuPG is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
19
 */
 
20
 
 
21
#include <config.h>
 
22
#include <errno.h>
 
23
#include <stdio.h>
 
24
#include <string.h>
 
25
#ifdef _WIN32 
 
26
# include <windows.h>
 
27
# ifndef VER_PLATFORM_WIN32_WINDOWS
 
28
#  define VER_PLATFORM_WIN32_WINDOWS 1
 
29
# endif
 
30
#endif
 
31
#include "packet.h"
 
32
#include "status.h"
 
33
#include "exec.h"
 
34
#include "keydb.h"
 
35
#include "util.h"
 
36
#include "i18n.h"
 
37
#include "iobuf.h"
 
38
#include "memory.h"
 
39
#include "options.h"
 
40
#include "main.h"
 
41
#include "photoid.h"
 
42
 
 
43
/* Generate a new photo id packet, or return NULL if canceled */
 
44
PKT_user_id *generate_photo_id(PKT_public_key *pk)
 
45
{
 
46
  PKT_user_id *uid;
 
47
  int error=1,i;
 
48
  unsigned int len;
 
49
  char *filename=NULL;
 
50
  byte *photo=NULL;
 
51
  byte header[16];
 
52
  iobuf_t file;
 
53
 
 
54
  header[0]=0x10; /* little side of photo header length */
 
55
  header[1]=0;    /* big side of photo header length */
 
56
  header[2]=1;    /* 1 == version of photo header */
 
57
  header[3]=1;    /* 1 == JPEG */
 
58
 
 
59
  for(i=4;i<16;i++) /* The reserved bytes */
 
60
    header[i]=0;
 
61
 
 
62
#define EXTRA_UID_NAME_SPACE 71
 
63
  uid=xcalloc (1,sizeof(*uid)+71);
 
64
 
 
65
  printf(_("\nPick an image to use for your photo ID.  "
 
66
           "The image must be a JPEG file.\n"
 
67
           "Remember that the image is stored within your public key.  "
 
68
           "If you use a\n"
 
69
           "very large picture, your key will become very large as well!\n"
 
70
           "Keeping the image close to 240x288 is a good size to use.\n"));
 
71
 
 
72
  while(photo==NULL)
 
73
    {
 
74
      printf("\n");
 
75
 
 
76
      xfree (filename);
 
77
 
 
78
      filename=cpr_get("photoid.jpeg.add",
 
79
                       _("Enter JPEG filename for photo ID: "));
 
80
 
 
81
      if(strlen(filename)==0)
 
82
        goto scram;
 
83
 
 
84
      file=iobuf_open(filename);
 
85
      if(!file)
 
86
        {
 
87
          log_error(_("Unable to open photo \"%s\": %s\n"),
 
88
                    filename,strerror(errno));
 
89
          continue;
 
90
        }
 
91
 
 
92
      len=iobuf_get_filelength(file);
 
93
      if(len>6144)
 
94
        {
 
95
          printf("This JPEG is really large (%d bytes) !\n",len);
 
96
          if(!cpr_get_answer_is_yes("photoid.jpeg.size",
 
97
                            _("Are you sure you want to use it (y/N)? ")))
 
98
          {
 
99
            iobuf_close(file);
 
100
            continue;
 
101
          }
 
102
        }
 
103
 
 
104
      photo=xmalloc (len);
 
105
      iobuf_read(file,photo,len);
 
106
      iobuf_close(file);
 
107
 
 
108
      /* Is it a JPEG? */
 
109
      if(photo[0]!=0xFF || photo[1]!=0xD8 ||
 
110
         photo[6]!='J' || photo[7]!='F' || photo[8]!='I' || photo[9]!='F')
 
111
        {
 
112
          log_error(_("\"%s\" is not a JPEG file\n"),filename);
 
113
          xfree (photo);
 
114
          photo=NULL;
 
115
          continue;
 
116
        }
 
117
 
 
118
      /* Build the packet */
 
119
      build_attribute_subpkt(uid,1,photo,len,header,16);
 
120
      parse_attribute_subpkts(uid);
 
121
      make_attribute_uidname(uid, EXTRA_UID_NAME_SPACE);
 
122
 
 
123
      /* Showing the photo is not safe when noninteractive since the
 
124
         "user" may not be able to dismiss a viewer window! */
 
125
      if(opt.command_fd==-1)
 
126
        {
 
127
          show_photos(uid->attribs,uid->numattribs,pk,NULL);
 
128
          switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay",
 
129
                                         _("Is this photo correct (y/N/q)? ")))
 
130
            {
 
131
            case -1:
 
132
              goto scram;
 
133
            case 0:
 
134
              free_attributes(uid);
 
135
              xfree (photo);
 
136
              photo=NULL;
 
137
              continue;
 
138
            }
 
139
        }
 
140
    }
 
141
 
 
142
  error=0;
 
143
  uid->ref=1;
 
144
 
 
145
 scram:
 
146
  xfree (filename);
 
147
  xfree (photo);
 
148
 
 
149
  if(error)
 
150
    {
 
151
      free_attributes(uid);
 
152
      xfree (uid);
 
153
      return NULL;
 
154
    }
 
155
 
 
156
  return uid;
 
157
}
 
158
 
 
159
/* Returns 0 for error, 1 for valid */
 
160
int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len)
 
161
{
 
162
  u16 headerlen;
 
163
 
 
164
  if(attr->len<3)
 
165
    return 0;
 
166
 
 
167
  /* For historical reasons (i.e. "oops!"), the header length is
 
168
     little endian. */
 
169
  headerlen=(attr->data[1]<<8) | attr->data[0];
 
170
 
 
171
  if(headerlen>attr->len)
 
172
    return 0;
 
173
 
 
174
  if(type && attr->len>=4)
 
175
    {
 
176
      if(attr->data[2]==1) /* header version 1 */
 
177
        *type=attr->data[3];
 
178
      else
 
179
        *type=0;
 
180
    }
 
181
 
 
182
  *len=attr->len-headerlen;
 
183
 
 
184
  if(*len==0)
 
185
    return 0;
 
186
 
 
187
  return 1;
 
188
}
 
189
 
 
190
/* style==0 for extension, 1 for name, 2 for MIME type.  Remember that
 
191
   the "name" style string could be used in a user ID name field, so
 
192
   make sure it is not too big (see parse-packet.c:parse_attribute).
 
193
   Extensions should be 3 characters long for the best cross-platform
 
194
   compatibility. */
 
195
char *image_type_to_string(byte type,int style)
 
196
{
 
197
  char *string;
 
198
 
 
199
  switch(type)
 
200
    {
 
201
    case 1: /* jpeg */
 
202
      if(style==0)
 
203
        string="jpg";
 
204
      else if(style==1)
 
205
        string="jpeg";
 
206
      else
 
207
        string="image/jpeg";
 
208
      break;
 
209
 
 
210
    default:
 
211
      if(style==0)
 
212
        string="bin";
 
213
      else if(style==1)
 
214
        string="unknown";
 
215
      else
 
216
        string="image/x-unknown";
 
217
      break;
 
218
    }
 
219
 
 
220
  return string;
 
221
}
 
222
 
 
223
#if !defined(FIXED_PHOTO_VIEWER) && !defined(DISABLE_PHOTO_VIEWER)
 
224
static const char *get_default_photo_command(void)
 
225
{
 
226
#if defined(_WIN32)
 
227
  OSVERSIONINFO osvi;
 
228
 
 
229
  memset(&osvi,0,sizeof(osvi));
 
230
  osvi.dwOSVersionInfoSize=sizeof(osvi);
 
231
  GetVersionEx(&osvi);
 
232
 
 
233
  if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
 
234
    return "start /w %i";
 
235
  else
 
236
    return "cmd /c start /w %i";
 
237
#elif defined(__APPLE__)
 
238
  /* OS X.  This really needs more than just __APPLE__. */
 
239
  return "open %I";
 
240
#elif defined(__riscos__)
 
241
  return "Filer_Run %I";
 
242
#else
 
243
  return "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin";
 
244
#endif
 
245
}
 
246
#endif
 
247
 
 
248
void show_photos(const struct user_attribute *attrs,
 
249
                 int count,PKT_public_key *pk,PKT_secret_key *sk)
 
250
{
 
251
#ifndef DISABLE_PHOTO_VIEWER
 
252
  int i;
 
253
  struct expando_args args;
 
254
  u32 len;
 
255
  u32 kid[2]={0,0};
 
256
 
 
257
  memset(&args,0,sizeof(args));
 
258
  args.pk=pk;
 
259
  args.sk=sk;
 
260
 
 
261
  if(pk)
 
262
    keyid_from_pk(pk,kid);
 
263
  else if(sk)
 
264
    keyid_from_sk(sk,kid);
 
265
 
 
266
  for(i=0;i<count;i++)
 
267
    if(attrs[i].type==ATTRIB_IMAGE &&
 
268
       parse_image_header(&attrs[i],&args.imagetype,&len))
 
269
      {
 
270
        char *command,*name;
 
271
        struct exec_info *spawn;
 
272
        int offset=attrs[i].len-len;
 
273
 
 
274
#ifdef FIXED_PHOTO_VIEWER
 
275
        opt.photo_viewer=FIXED_PHOTO_VIEWER;
 
276
#else
 
277
        if(!opt.photo_viewer)
 
278
          opt.photo_viewer=get_default_photo_command();
 
279
#endif
 
280
 
 
281
        /* make command grow */
 
282
        command=pct_expando(opt.photo_viewer,&args);
 
283
        if(!command)
 
284
          goto fail;
 
285
 
 
286
        name=xmalloc (16+strlen(EXTSEP_S)+
 
287
                     strlen(image_type_to_string(args.imagetype,0))+1);
 
288
 
 
289
        /* Make the filename.  Notice we are not using the image
 
290
           encoding type for more than cosmetics.  Most external image
 
291
           viewers can handle a multitude of types, and even if one
 
292
           cannot understand a particular type, we have no way to know
 
293
           which.  The spec permits this, by the way. -dms */
 
294
 
 
295
#ifdef USE_ONLY_8DOT3
 
296
        sprintf(name,"%08lX" EXTSEP_S "%s",(ulong)kid[1],
 
297
                image_type_to_string(args.imagetype,0));
 
298
#else
 
299
        sprintf(name,"%08lX%08lX" EXTSEP_S "%s",(ulong)kid[0],(ulong)kid[1],
 
300
                image_type_to_string(args.imagetype,0));
 
301
#endif
 
302
 
 
303
        if(exec_write(&spawn,NULL,command,name,1,1)!=0)
 
304
          {
 
305
            xfree (name);
 
306
            goto fail;
 
307
          }
 
308
 
 
309
#ifdef __riscos__
 
310
        riscos_set_filetype_by_mimetype(spawn->tempfile_in,
 
311
                                        image_type_to_string(args.imagetype,2));
 
312
#endif
 
313
 
 
314
        xfree (name);
 
315
 
 
316
        fwrite(&attrs[i].data[offset],attrs[i].len-offset,1,spawn->tochild);
 
317
 
 
318
        if(exec_read(spawn)!=0)
 
319
          {
 
320
            exec_finish(spawn);
 
321
            goto fail;
 
322
          }
 
323
 
 
324
        if(exec_finish(spawn)!=0)
 
325
          goto fail;
 
326
      }
 
327
 
 
328
  return;
 
329
 
 
330
 fail:
 
331
  log_error(_("unable to display photo ID!\n"));
 
332
#endif
 
333
}