1 /* photoid.c - photo ID handling code
2 * Copyright (C) 2001, 2002, 2005 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 2 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, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
28 # ifndef VER_PLATFORM_WIN32_WINDOWS
29 # define VER_PLATFORM_WIN32_WINDOWS 1
46 /* Generate a new photo id packet, or return NULL if canceled */
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
);
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";
287 void show_photos(const struct user_attribute
*attrs
,
288 int count
,PKT_public_key
*pk
,PKT_secret_key
*sk
)
290 #ifndef DISABLE_PHOTO_VIEWER
292 struct expando_args args
;
296 memset(&args
,0,sizeof(args
));
301 keyid_from_pk(pk
,kid
);
303 keyid_from_sk(sk
,kid
);
306 if(attrs
[i
].type
==ATTRIB_IMAGE
&&
307 parse_image_header(&attrs
[i
],&args
.imagetype
,&len
))
310 struct exec_info
*spawn
;
311 int offset
=attrs
[i
].len
-len
;
313 #ifdef FIXED_PHOTO_VIEWER
314 opt
.photo_viewer
=FIXED_PHOTO_VIEWER
;
316 if(!opt
.photo_viewer
)
317 opt
.photo_viewer
=get_default_photo_command();
320 /* make command grow */
321 command
=pct_expando(opt
.photo_viewer
,&args
);
325 name
=xmalloc(16+strlen(EXTSEP_S
)+
326 strlen(image_type_to_string(args
.imagetype
,0))+1);
328 /* Make the filename. Notice we are not using the image
329 encoding type for more than cosmetics. Most external image
330 viewers can handle a multitude of types, and even if one
331 cannot understand a particular type, we have no way to know
332 which. The spec permits this, by the way. -dms */
334 #ifdef USE_ONLY_8DOT3
335 sprintf(name
,"%08lX" EXTSEP_S
"%s",(ulong
)kid
[1],
336 image_type_to_string(args
.imagetype
,0));
338 sprintf(name
,"%08lX%08lX" EXTSEP_S
"%s",(ulong
)kid
[0],(ulong
)kid
[1],
339 image_type_to_string(args
.imagetype
,0));
342 if(exec_write(&spawn
,NULL
,command
,name
,1,1)!=0)
349 riscos_set_filetype_by_mimetype(spawn
->tempfile_in
,
350 image_type_to_string(args
.imagetype
,2));
355 fwrite(&attrs
[i
].data
[offset
],attrs
[i
].len
-offset
,1,spawn
->tochild
);
357 if(exec_read(spawn
)!=0)
363 if(exec_finish(spawn
)!=0)
370 log_error(_("unable to display photo ID!\n"));