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 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
44 /* Generate a new photo id packet, or return NULL if canceled */
46 generate_photo_id(PKT_public_key
*pk
,const char *photo_name
)
57 header
[0]=0x10; /* little side of photo header length */
58 header
[1]=0; /* big side of photo header length */
59 header
[2]=1; /* 1 == version of photo header */
60 header
[3]=1; /* 1 == JPEG */
62 for(i
=4;i
<16;i
++) /* The reserved bytes */
65 #define EXTRA_UID_NAME_SPACE 71
66 uid
=xmalloc_clear(sizeof(*uid
)+71);
68 if(photo_name
&& *photo_name
)
69 filename
=make_filename(photo_name
,(void *)NULL
);
72 tty_printf(_("\nPick an image to use for your photo ID."
73 " The image must be a JPEG file.\n"
74 "Remember that the image is stored within your public key."
76 "very large picture, your key will become very large"
78 "Keeping the image close to 240x288 is a good size"
91 tty_enable_completion(NULL
);
93 tempname
=cpr_get("photoid.jpeg.add",
94 _("Enter JPEG filename for photo ID: "));
96 tty_disable_completion();
98 filename
=make_filename(tempname
,(void *)NULL
);
102 if(strlen(filename
)==0)
106 file
=iobuf_open(filename
);
107 if (file
&& is_secured_file (iobuf_get_fd (file
)))
115 log_error(_("unable to open JPEG file `%s': %s\n"),
116 filename
,strerror(errno
));
123 len
=iobuf_get_filelength(file
, &overflow
);
124 if(len
>6144 || overflow
)
126 tty_printf( _("This JPEG is really large (%d bytes) !\n"),len
);
127 if(!cpr_get_answer_is_yes("photoid.jpeg.size",
128 _("Are you sure you want to use it? (y/N) ")))
138 iobuf_read(file
,photo
,len
);
142 if(photo
[0]!=0xFF || photo
[1]!=0xD8 ||
143 photo
[6]!='J' || photo
[7]!='F' || photo
[8]!='I' || photo
[9]!='F')
145 log_error(_("`%s' is not a JPEG file\n"),filename
);
153 /* Build the packet */
154 build_attribute_subpkt(uid
,1,photo
,len
,header
,16);
155 parse_attribute_subpkts(uid
);
156 make_attribute_uidname(uid
, EXTRA_UID_NAME_SPACE
);
158 /* Showing the photo is not safe when noninteractive since the
159 "user" may not be able to dismiss a viewer window! */
160 if(opt
.command_fd
==-1)
162 show_photos(uid
->attribs
,uid
->numattribs
,pk
,NULL
);
163 switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay",
164 _("Is this photo correct (y/N/q)? ")))
169 free_attributes(uid
);
188 free_attributes(uid
);
196 /* Returns 0 for error, 1 for valid */
197 int parse_image_header(const struct user_attribute
*attr
,byte
*type
,u32
*len
)
204 /* For historical reasons (i.e. "oops!"), the header length is
206 headerlen
=(attr
->data
[1]<<8) | attr
->data
[0];
208 if(headerlen
>attr
->len
)
211 if(type
&& attr
->len
>=4)
213 if(attr
->data
[2]==1) /* header version 1 */
219 *len
=attr
->len
-headerlen
;
227 /* style==0 for extension, 1 for name, 2 for MIME type. Remember that
228 the "name" style string could be used in a user ID name field, so
229 make sure it is not too big (see parse-packet.c:parse_attribute).
230 Extensions should be 3 characters long for the best cross-platform
232 char *image_type_to_string(byte type
,int style
)
253 string
="image/x-unknown";
260 #if !defined(FIXED_PHOTO_VIEWER) && !defined(DISABLE_PHOTO_VIEWER)
261 static const char *get_default_photo_command(void)
266 memset(&osvi
,0,sizeof(osvi
));
267 osvi
.dwOSVersionInfoSize
=sizeof(osvi
);
270 if(osvi
.dwPlatformId
==VER_PLATFORM_WIN32_WINDOWS
)
271 return "start /w %i";
273 return "cmd /c start /w %i";
274 #elif defined(__APPLE__)
275 /* OS X. This really needs more than just __APPLE__. */
277 #elif defined(__riscos__)
278 return "Filer_Run %I";
280 return "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin";
285 void show_photos(const struct user_attribute
*attrs
,
286 int count
,PKT_public_key
*pk
,PKT_secret_key
*sk
)
288 #ifndef DISABLE_PHOTO_VIEWER
290 struct expando_args args
;
294 memset(&args
,0,sizeof(args
));
299 keyid_from_pk(pk
,kid
);
301 keyid_from_sk(sk
,kid
);
304 if(attrs
[i
].type
==ATTRIB_IMAGE
&&
305 parse_image_header(&attrs
[i
],&args
.imagetype
,&len
))
308 struct exec_info
*spawn
;
309 int offset
=attrs
[i
].len
-len
;
311 #ifdef FIXED_PHOTO_VIEWER
312 opt
.photo_viewer
=FIXED_PHOTO_VIEWER
;
314 if(!opt
.photo_viewer
)
315 opt
.photo_viewer
=get_default_photo_command();
318 /* make command grow */
319 command
=pct_expando(opt
.photo_viewer
,&args
);
323 name
=xmalloc(16+strlen(EXTSEP_S
)+
324 strlen(image_type_to_string(args
.imagetype
,0))+1);
326 /* Make the filename. Notice we are not using the image
327 encoding type for more than cosmetics. Most external image
328 viewers can handle a multitude of types, and even if one
329 cannot understand a particular type, we have no way to know
330 which. The spec permits this, by the way. -dms */
332 #ifdef USE_ONLY_8DOT3
333 sprintf(name
,"%08lX" EXTSEP_S
"%s",(ulong
)kid
[1],
334 image_type_to_string(args
.imagetype
,0));
336 sprintf(name
,"%08lX%08lX" EXTSEP_S
"%s",(ulong
)kid
[0],(ulong
)kid
[1],
337 image_type_to_string(args
.imagetype
,0));
340 if(exec_write(&spawn
,NULL
,command
,name
,1,1)!=0)
347 riscos_set_filetype_by_mimetype(spawn
->tempfile_in
,
348 image_type_to_string(args
.imagetype
,2));
353 fwrite(&attrs
[i
].data
[offset
],attrs
[i
].len
-offset
,1,spawn
->tochild
);
355 if(exec_read(spawn
)!=0)
361 if(exec_finish(spawn
)!=0)
368 log_error(_("unable to display photo ID!\n"));