1 /* photoid.c - photo ID handling code
2 * Copyright (C) 2001, 2002, 2005, 2006, 2008 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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 3 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 # ifndef VER_PLATFORM_WIN32_WINDOWS
27 # define VER_PLATFORM_WIN32_WINDOWS 1
45 /* Generate a new photo id packet, or return NULL if canceled.
46 FIXME: Should we add a duplicates check similar to generate_user_id? */
48 generate_photo_id(PKT_public_key
*pk
,const char *photo_name
)
59 header
[0]=0x10; /* little side of photo header length */
60 header
[1]=0; /* big side of photo header length */
61 header
[2]=1; /* 1 == version of photo header */
62 header
[3]=1; /* 1 == JPEG */
64 for(i
=4;i
<16;i
++) /* The reserved bytes */
67 #define EXTRA_UID_NAME_SPACE 71
68 uid
=xmalloc_clear(sizeof(*uid
)+71);
70 if(photo_name
&& *photo_name
)
71 filename
=make_filename(photo_name
,(void *)NULL
);
74 tty_printf(_("\nPick an image to use for your photo ID."
75 " The image must be a JPEG file.\n"
76 "Remember that the image is stored within your public key."
78 "very large picture, your key will become very large"
80 "Keeping the image close to 240x288 is a good size"
93 tty_enable_completion(NULL
);
95 tempname
=cpr_get("photoid.jpeg.add",
96 _("Enter JPEG filename for photo ID: "));
98 tty_disable_completion();
100 filename
=make_filename(tempname
,(void *)NULL
);
104 if(strlen(filename
)==0)
108 file
=iobuf_open(filename
);
109 if (file
&& is_secured_file (iobuf_get_fd (file
)))
117 log_error(_("unable to open JPEG file `%s': %s\n"),
118 filename
,strerror(errno
));
125 len
=iobuf_get_filelength(file
, &overflow
);
126 if(len
>6144 || overflow
)
128 tty_printf( _("This JPEG is really large (%d bytes) !\n"),len
);
129 if(!cpr_get_answer_is_yes("photoid.jpeg.size",
130 _("Are you sure you want to use it? (y/N) ")))
140 iobuf_read(file
,photo
,len
);
144 if(photo
[0]!=0xFF || photo
[1]!=0xD8 ||
145 photo
[6]!='J' || photo
[7]!='F' || photo
[8]!='I' || photo
[9]!='F')
147 log_error(_("`%s' is not a JPEG file\n"),filename
);
155 /* Build the packet */
156 build_attribute_subpkt(uid
,1,photo
,len
,header
,16);
157 parse_attribute_subpkts(uid
);
158 make_attribute_uidname(uid
, EXTRA_UID_NAME_SPACE
);
160 /* Showing the photo is not safe when noninteractive since the
161 "user" may not be able to dismiss a viewer window! */
162 if(opt
.command_fd
==-1)
164 show_photos(uid
->attribs
,uid
->numattribs
,pk
,NULL
,uid
);
165 switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay",
166 _("Is this photo correct (y/N/q)? ")))
171 free_attributes(uid
);
190 free_attributes(uid
);
198 /* Returns 0 for error, 1 for valid */
199 int parse_image_header(const struct user_attribute
*attr
,byte
*type
,u32
*len
)
206 /* For historical reasons (i.e. "oops!"), the header length is
208 headerlen
=(attr
->data
[1]<<8) | attr
->data
[0];
210 if(headerlen
>attr
->len
)
213 if(type
&& attr
->len
>=4)
215 if(attr
->data
[2]==1) /* header version 1 */
221 *len
=attr
->len
-headerlen
;
229 /* style==0 for extension, 1 for name, 2 for MIME type. Remember that
230 the "name" style string could be used in a user ID name field, so
231 make sure it is not too big (see parse-packet.c:parse_attribute).
232 Extensions should be 3 characters long for the best cross-platform
234 char *image_type_to_string(byte type
,int style
)
255 string
="image/x-unknown";
262 #if !defined(FIXED_PHOTO_VIEWER) && !defined(DISABLE_PHOTO_VIEWER)
263 static const char *get_default_photo_command(void)
268 memset(&osvi
,0,sizeof(osvi
));
269 osvi
.dwOSVersionInfoSize
=sizeof(osvi
);
272 if(osvi
.dwPlatformId
==VER_PLATFORM_WIN32_WINDOWS
)
273 return "start /w %i";
275 return "cmd /c start /w %i";
276 #elif defined(__APPLE__)
277 /* OS X. This really needs more than just __APPLE__. */
279 #elif defined(__riscos__)
280 return "Filer_Run %I";
282 return "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin";
288 show_photos(const struct user_attribute
*attrs
,
289 int count
,PKT_public_key
*pk
,PKT_secret_key
*sk
,
292 #ifndef DISABLE_PHOTO_VIEWER
294 struct expando_args args
;
298 memset(&args
,0,sizeof(args
));
301 args
.validity_info
=get_validity_info(pk
,uid
);
302 args
.validity_string
=get_validity_string(pk
,uid
);
305 keyid_from_pk(pk
,kid
);
307 keyid_from_sk(sk
,kid
);
310 if(attrs
[i
].type
==ATTRIB_IMAGE
&&
311 parse_image_header(&attrs
[i
],&args
.imagetype
,&len
))
314 struct exec_info
*spawn
;
315 int offset
=attrs
[i
].len
-len
;
317 #ifdef FIXED_PHOTO_VIEWER
318 opt
.photo_viewer
=FIXED_PHOTO_VIEWER
;
320 if(!opt
.photo_viewer
)
321 opt
.photo_viewer
=get_default_photo_command();
324 /* make command grow */
325 command
=pct_expando(opt
.photo_viewer
,&args
);
329 name
=xmalloc(16+strlen(EXTSEP_S
)+
330 strlen(image_type_to_string(args
.imagetype
,0))+1);
332 /* Make the filename. Notice we are not using the image
333 encoding type for more than cosmetics. Most external image
334 viewers can handle a multitude of types, and even if one
335 cannot understand a particular type, we have no way to know
336 which. The spec permits this, by the way. -dms */
338 #ifdef USE_ONLY_8DOT3
339 sprintf(name
,"%08lX" EXTSEP_S
"%s",(ulong
)kid
[1],
340 image_type_to_string(args
.imagetype
,0));
342 sprintf(name
,"%08lX%08lX" EXTSEP_S
"%s",(ulong
)kid
[0],(ulong
)kid
[1],
343 image_type_to_string(args
.imagetype
,0));
346 if(exec_write(&spawn
,NULL
,command
,name
,1,1)!=0)
353 riscos_set_filetype_by_mimetype(spawn
->tempfile_in
,
354 image_type_to_string(args
.imagetype
,2));
359 fwrite(&attrs
[i
].data
[offset
],attrs
[i
].len
-offset
,1,spawn
->tochild
);
361 if(exec_read(spawn
)!=0)
367 if(exec_finish(spawn
)!=0)
374 log_error(_("unable to display photo ID!\n"));