1 /* photoid.c - photo ID handling code
2 * Copyright (C) 2001, 2002, 2005, 2006, 2008, 2011 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 <https://www.gnu.org/licenses/>.
25 # ifdef HAVE_WINSOCK2_H
26 # include <winsock2.h>
29 # ifndef VER_PLATFORM_WIN32_WINDOWS
30 # define VER_PLATFORM_WIN32_WINDOWS 1
48 /* Generate a new photo id packet, or return NULL if canceled.
49 FIXME: Should we add a duplicates check similar to generate_user_id? */
51 generate_photo_id (ctrl_t ctrl, PKT_public_key *pk,const char *photo_name)
62 header[0]=0x10; /* little side of photo header length */
63 header[1]=0; /* big side of photo header length */
64 header[2]=1; /* 1 == version of photo header */
65 header[3]=1; /* 1 == JPEG */
67 for(i=4;i<16;i++) /* The reserved bytes */
70 #define EXTRA_UID_NAME_SPACE 71
71 uid=xmalloc_clear(sizeof(*uid)+71);
73 if(photo_name && *photo_name)
74 filename=make_filename(photo_name,(void *)NULL);
77 tty_printf(_("\nPick an image to use for your photo ID."
78 " The image must be a JPEG file.\n"
79 "Remember that the image is stored within your public key."
81 "very large picture, your key will become very large"
83 "Keeping the image close to 240x288 is a good size"
96 tty_enable_completion(NULL);
98 tempname=cpr_get("photoid.jpeg.add",
99 _("Enter JPEG filename for photo ID: "));
101 tty_disable_completion();
103 filename=make_filename(tempname,(void *)NULL);
107 if(strlen(filename)==0)
111 file=iobuf_open(filename);
112 if (file && is_secured_file (iobuf_get_fd (file)))
116 gpg_err_set_errno (EPERM);
120 log_error(_("unable to open JPEG file '%s': %s\n"),
121 filename,strerror(errno));
128 len=iobuf_get_filelength(file, &overflow);
129 if(len>6144 || overflow)
131 tty_printf( _("This JPEG is really large (%d bytes) !\n"),len);
132 if(!cpr_get_answer_is_yes("photoid.jpeg.size",
133 _("Are you sure you want to use it? (y/N) ")))
143 iobuf_read(file,photo,len);
147 if(photo[0]!=0xFF || photo[1]!=0xD8)
149 log_error(_("'%s' is not a JPEG file\n"),filename);
157 /* Build the packet */
158 build_attribute_subpkt(uid,1,photo,len,header,16);
159 parse_attribute_subpkts(uid);
160 make_attribute_uidname(uid, EXTRA_UID_NAME_SPACE);
162 /* Showing the photo is not safe when noninteractive since the
163 "user" may not be able to dismiss a viewer window! */
164 if(opt.command_fd==-1)
166 show_photos (ctrl, uid->attribs, uid->numattribs, pk, uid);
167 switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay",
168 _("Is this photo correct (y/N/q)? ")))
173 free_attributes(uid);
192 free_attributes(uid);
200 /* Returns 0 for error, 1 for valid */
201 int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len)
208 /* For historical reasons (i.e. "oops!"), the header length is
210 headerlen=(attr->data[1]<<8) | attr->data[0];
212 if(headerlen>attr->len)
215 if(type && attr->len>=4)
217 if(attr->data[2]==1) /* header version 1 */
223 *len=attr->len-headerlen;
231 /* style==0 for extension, 1 for name, 2 for MIME type. Remember that
232 the "name" style string could be used in a user ID name field, so
233 make sure it is not too big (see parse-packet.c:parse_attribute).
234 Extensions should be 3 characters long for the best cross-platform
236 char *image_type_to_string(byte type,int style)
257 string="image/x-unknown";
264 #if !defined(FIXED_PHOTO_VIEWER) && !defined(DISABLE_PHOTO_VIEWER)
265 static const char *get_default_photo_command(void)
270 memset(&osvi,0,sizeof(osvi));
271 osvi.dwOSVersionInfoSize=sizeof(osvi);
274 if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
275 return "start /w %i";
277 return "cmd /c start /w %i";
278 #elif defined(__APPLE__)
279 /* OS X. This really needs more than just __APPLE__. */
281 #elif defined(__riscos__)
282 return "Filer_Run %I";
284 return "xloadimage -fork -quiet -title 'KeyID 0x%k' stdin";
291 show_photos (ctrl_t ctrl, const struct user_attribute *attrs, int count,
292 PKT_public_key *pk, PKT_user_id *uid)
294 #ifdef DISABLE_PHOTO_VIEWER
299 #else /*!DISABLE_PHOTO_VIEWER*/
301 struct expando_args args;
305 memset (&args, 0, sizeof(args));
307 args.validity_info = get_validity_info (ctrl, NULL, pk, uid);
308 args.validity_string = get_validity_string (ctrl, pk, uid);
309 namehash_from_uid (uid);
310 args.namehash = uid->namehash;
313 keyid_from_pk (pk, kid);
316 if(attrs[i].type==ATTRIB_IMAGE &&
317 parse_image_header(&attrs[i],&args.imagetype,&len))
320 struct exec_info *spawn;
321 int offset=attrs[i].len-len;
323 #ifdef FIXED_PHOTO_VIEWER
324 opt.photo_viewer=FIXED_PHOTO_VIEWER;
326 if(!opt.photo_viewer)
327 opt.photo_viewer=get_default_photo_command();
330 /* make command grow */
331 command=pct_expando(opt.photo_viewer,&args);
335 name=xmalloc(16+strlen(EXTSEP_S)+
336 strlen(image_type_to_string(args.imagetype,0))+1);
338 /* Make the filename. Notice we are not using the image
339 encoding type for more than cosmetics. Most external image
340 viewers can handle a multitude of types, and even if one
341 cannot understand a particular type, we have no way to know
342 which. The spec permits this, by the way. -dms */
344 #ifdef USE_ONLY_8DOT3
345 sprintf(name,"%08lX" EXTSEP_S "%s",(ulong)kid[1],
346 image_type_to_string(args.imagetype,0));
348 sprintf(name,"%08lX%08lX" EXTSEP_S "%s",(ulong)kid[0],(ulong)kid[1],
349 image_type_to_string(args.imagetype,0));
352 if(exec_write(&spawn,NULL,command,name,1,1)!=0)
359 riscos_set_filetype_by_mimetype(spawn->tempfile_in,
360 image_type_to_string(args.imagetype,2));
365 fwrite(&attrs[i].data[offset],attrs[i].len-offset,1,spawn->tochild);
367 if(exec_read(spawn)!=0)
373 if(exec_finish(spawn)!=0)
380 log_error(_("unable to display photo ID!\n"));
381 #endif /*!DISABLE_PHOTO_VIEWER*/