aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--g10/ChangeLog21
-rw-r--r--g10/gpgv.c6
-rw-r--r--g10/keyedit.c56
-rw-r--r--g10/keylist.c6
-rw-r--r--g10/main.h9
-rw-r--r--g10/misc.c147
-rw-r--r--g10/packet.h8
-rw-r--r--g10/parse-packet.c50
-rw-r--r--g10/photoid.c116
-rw-r--r--g10/photoid.h4
-rw-r--r--g10/sign.c19
11 files changed, 284 insertions, 158 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 16d114af8..424e03daa 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,5 +1,26 @@
2002-05-02 David Shaw <[email protected]>
+ * photoid.h, photoid.c (parse_image_header, image_type_to_string):
+ Useful functions to return data about an image.
+
+ * packet.h, parse-packet.c (make_attribute_uidname,
+ parse_attribute_subpkts, parse_attribute), photoid.h, photoid.c
+ (show_photos): Handle multiple images in a single attribute
+ packet.
+
+ * main.h, misc.c (pct_expando), sign.c (mk_notation_and_policy),
+ photoid.c (show_photos): Simpler expando code that does not
+ require using compile-time string sizes. Call
+ image_type_to_string to get image strings (i.e. "jpg",
+ "image/jpeg"). Change all callers.
+
+ * keyedit.c (menu_showphoto), keylist.c (list_keyblock_print):
+ Allow viewing multiple images within a single attribute packet.
+
+ * gpgv.c: Various stubs for link happiness.
+
+2002-05-02 David Shaw <[email protected]>
+
* build-packet.c (build_sig_subpkt), keyedit.c (sign_uids),
options.h, sign.c (mk_notation_and_policy), g10.c (main,
add_notation_data, add_policy_url (new), check_policy_url
diff --git a/g10/gpgv.c b/g10/gpgv.c
index 03440358a..0d9be3402 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -301,8 +301,10 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
return NULL;
}
-/* Stub to avoid linking to photoid.c */
-void show_photo(const struct user_attribute *attr,PKT_public_key *pk) {}
+/* Stubs to avoid linking to photoid.c */
+void show_photos(const struct user_attribute *attrs,int count,PKT_public_key *pk) {}
+int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len) {return 0;}
+char *image_type_to_string(byte type,int string) {return NULL;}
/* Stubs to void linking to ../cipher/cipher.c */
int string_to_cipher_algo( const char *string ) { return 0; }
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 858344ceb..b2c61a1d2 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -2131,7 +2131,7 @@ menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock )
action = selected? 0 : -1;
else /* no */
action = selected? 1 : 0;
-
+
if (action) {
int rc = update_keysig_packet (&newsig, sig,
main_pk, uid,
@@ -2684,30 +2684,36 @@ menu_showphoto( KBNODE keyblock )
for( node = keyblock; node; node = node->next )
{
if( node->pkt->pkttype == PKT_PUBLIC_KEY )
- pk = node->pkt->pkt.public_key;
- }
+ {
+ pk = node->pkt->pkt.public_key;
+ keyid_from_pk(pk, keyid);
+ }
+ else if( node->pkt->pkttype == PKT_USER_ID )
+ {
+ PKT_user_id *uid = node->pkt->pkt.user_id;
+ count++;
- for( node = keyblock; node; node = node->next )
- {
- if( node->pkt->pkttype == PKT_USER_ID )
- {
- PKT_user_id *uid = node->pkt->pkt.user_id;
- count++;
-
- if((select_all || (node->flag & NODFLG_SELUID)) &&
- uid->attribs!=NULL)
- {
- /* Can this really ever happen? */
- if(pk==NULL)
- keyid[1]=0;
- else
- keyid_from_pk(pk, keyid);
-
- tty_printf(_("Displaying %s photo ID of size %ld "
- "for key 0x%08lX (uid %d)\n"),
- "jpeg",uid->attribs->len,(ulong)keyid[1],count);
- show_photo(uid->attribs,pk);
- }
- }
+ if((select_all || (node->flag & NODFLG_SELUID)) &&
+ uid->attribs!=NULL)
+ {
+ int i;
+
+ for(i=0;i<uid->numattribs;i++)
+ {
+ byte type;
+ u32 size;
+
+ if(uid->attribs[i].type==ATTRIB_IMAGE &&
+ parse_image_header(&uid->attribs[i],&type,&size))
+ {
+ tty_printf(_("Displaying %s photo ID of size %ld for "
+ "key 0x%08lX (uid %d)\n"),
+ image_type_to_string(type,1),
+ (ulong)size,(ulong)keyid[1],count);
+ show_photos(&uid->attribs[i],1,pk);
+ }
+ }
+ }
+ }
}
}
diff --git a/g10/keylist.c b/g10/keylist.c
index 15a80af72..57df6c232 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -399,9 +399,9 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque )
any = 1;
}
- if(opt.show_photos && node->pkt->pkt.user_id->attribs!=NULL &&
- node->pkt->pkt.user_id->attribs->type==ATTRIB_JPEG)
- show_photo(node->pkt->pkt.user_id->attribs,pk);
+ if(opt.show_photos && node->pkt->pkt.user_id->attribs!=NULL)
+ show_photos(node->pkt->pkt.user_id->attribs,
+ node->pkt->pkt.user_id->numattribs,pk);
}
else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
u32 keyid2[2];
diff --git a/g10/main.h b/g10/main.h
index a63df5349..6f29e6fed 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -67,7 +67,14 @@ int openpgp_pk_algo_usage ( int algo );
int openpgp_md_test_algo( int algo );
int check_permissions(const char *path,int extension,int checkonly);
void idea_cipher_warn( int show );
-char *pct_expando(const char *string,PKT_public_key *pk);
+
+struct expando_args
+{
+ PKT_public_key *pk;
+ byte imagetype;
+};
+
+char *pct_expando(const char *string,struct expando_args *args);
int hextobyte( const char *s );
/*-- helptext.c --*/
diff --git a/g10/misc.c b/g10/misc.c
index 0588965b2..4316d8f01 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -38,6 +38,7 @@
#endif
#include "util.h"
#include "main.h"
+#include "photoid.h"
#include "options.h"
#include "i18n.h"
@@ -439,55 +440,56 @@ idea_cipher_warn(int show)
}
}
-/* The largest string we have an expando for. */
-#define LARGEST_EXPANDO (MAX_FINGERPRINT_LEN*2)
-
/* Expand %-strings. Returns a string which must be m_freed. Returns
NULL if the string cannot be expanded (too large). */
char *
-pct_expando(const char *string,PKT_public_key *pk)
+pct_expando(const char *string,struct expando_args *args)
{
const char *ch=string;
- int idx=0,maxlen;
+ int idx=0,maxlen=0,done=0;
u32 keyid[2]={0,0};
- char *ret;
-
- keyid_from_pk(pk,keyid);
+ char *ret=NULL;
- maxlen=LARGEST_EXPANDO*2;
- ret=m_alloc(maxlen+1); /* one more to leave room for the trailing \0 */
-
- ret[0]='\0';
+ if(args->pk)
+ keyid_from_pk(args->pk,keyid);
while(*ch!='\0')
{
- /* 8192 is way bigger than we'll need here */
- if(maxlen-idx<LARGEST_EXPANDO && maxlen<8192)
+ char *str=NULL;
+
+ if(!done)
{
- maxlen+=LARGEST_EXPANDO*2;
- ret=m_realloc(ret,maxlen+1);
+ /* 8192 is way bigger than we'll need here */
+ if(maxlen>=8192)
+ goto fail;
+
+ maxlen+=1024;
+ ret=m_realloc(ret,maxlen);
}
+ done=0;
+
if(*ch=='%')
{
- ch++;
-
- switch(*ch)
+ switch(*(ch+1))
{
case 'k': /* short key id */
- if(idx+8>maxlen)
- goto fail;
-
- sprintf(&ret[idx],"%08lX",(ulong)keyid[1]);
- idx+=8;
+ if(idx+8<maxlen)
+ {
+ sprintf(&ret[idx],"%08lX",(ulong)keyid[1]);
+ idx+=8;
+ done=1;
+ }
break;
case 'K': /* long key id */
- if(idx+16>maxlen)
- goto fail;
-
- sprintf(&ret[idx],"%08lX%08lX",(ulong)keyid[0],(ulong)keyid[1]);
- idx+=16;
+ if(idx+16<maxlen)
+ {
+ sprintf(&ret[idx],"%08lX%08lX",
+ (ulong)keyid[0],(ulong)keyid[1]);
+ idx+=16;
+ done=1;
+ }
break;
case 'f': /* fingerprint */
@@ -496,43 +498,46 @@ pct_expando(const char *string,PKT_public_key *pk)
size_t len;
int i;
- fingerprint_from_pk(pk,array,&len);
-
- if(idx+(len*2)>maxlen)
- goto fail;
+ if(args->pk)
+ fingerprint_from_pk(args->pk,array,&len);
+ else
+ memset(array,0,MAX_FINGERPRINT_LEN);
- for(i=0;i<len;i++)
+ if(idx+(len*2)<maxlen)
{
- sprintf(&ret[idx],"%02X",array[i]);
- idx+=2;
+ for(i=0;i<len;i++)
+ {
+ sprintf(&ret[idx],"%02X",array[i]);
+ idx+=2;
+ }
+ done=1;
}
}
break;
- /* photo types. For now, it's always jpeg so this is
- easy! */
- case 't':
- if(idx+3>maxlen)
- goto fail;
+ case 't': /* e.g. "jpg" */
+ str=image_type_to_string(args->imagetype,1);
+ /* fall through */
- strcpy(&ret[idx],"jpg");
- idx+=3;
- break;
-
- case 'T':
- if(idx+10>maxlen)
- goto fail;
+ case 'T': /* e.g. "image/jpeg" */
+ if(str==NULL)
+ str=image_type_to_string(args->imagetype,2);
- strcpy(&ret[idx],"image/jpeg");
- idx+=10;
+ if(idx+strlen(str)<maxlen)
+ {
+ strcpy(&ret[idx],str);
+ idx+=strlen(str);
+ done=1;
+ }
break;
case '%':
- if(idx+1>maxlen)
- goto fail;
-
- ret[idx++]='%';
- ret[idx]='\0';
+ if(idx+1<maxlen)
+ {
+ ret[idx++]='%';
+ ret[idx]='\0';
+ done=1;
+ }
break;
/* Any unknown %-keys (like %i, %o, %I, and %O) are
@@ -541,25 +546,31 @@ pct_expando(const char *string,PKT_public_key *pk)
string is a '%' - the terminating \0 will end up here
and properly terminate the string. */
default:
- if(idx+2>maxlen)
- goto fail;
-
- ret[idx++]='%';
- ret[idx++]=*ch;
- ret[idx]='\0';
+ if(idx+2<maxlen)
+ {
+ ret[idx++]='%';
+ ret[idx++]=*(ch+1);
+ ret[idx]='\0';
+ done=1;
+ }
break;
- }
+ }
+
+ if(done)
+ ch++;
}
else
{
- if(idx+1>maxlen)
- goto fail;
-
- ret[idx++]=*ch;
- ret[idx]='\0';
+ if(idx+1<maxlen)
+ {
+ ret[idx++]=*ch;
+ ret[idx]='\0';
+ done=1;
+ }
}
- ch++;
+ if(done)
+ ch++;
}
return ret;
diff --git a/g10/packet.h b/g10/packet.h
index 43797a422..7ef9b3cda 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -148,15 +148,11 @@ typedef struct {
MPI data[PUBKEY_MAX_NSIG];
} PKT_signature;
-typedef enum
-{
- ATTRIB_UNKNOWN,
- ATTRIB_JPEG
-} attribtype_t;
+#define ATTRIB_IMAGE 1
/* This is the cooked form of attributes */
struct user_attribute {
- attribtype_t type;
+ byte type;
const byte *data;
unsigned long len;
};
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index b6ee4419a..ff5b0bb05 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -31,6 +31,7 @@
#include "cipher.h"
#include "memory.h"
#include "filter.h"
+#include "photoid.h"
#include "options.h"
#include "main.h"
#include "i18n.h"
@@ -1739,23 +1740,7 @@ parse_attribute_subpkts(PKT_user_id *uid)
buflen--;
n--;
- /* In order: is it an image, is it large enough to carry the
- image header, is it version 1, and is it a JPEG? */
- if(type==1 && n>=16 && buffer[2]==1 && buffer[3]==1)
- {
- /* For historical reasons (i.e. "oops!"), headerlen is
- little endian. */
- u16 headerlen=(buffer[1]<<8) | buffer[0];
-
- attribs[count].type=ATTRIB_JPEG;
-
- buffer+=headerlen;
- buflen-=headerlen;
- n-=headerlen;
- }
- else
- attribs[count].type=ATTRIB_UNKNOWN;
-
+ attribs[count].type=type;
attribs[count].data=buffer;
attribs[count].len=n;
buffer+=n;
@@ -1821,14 +1806,29 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
void
make_attribute_uidname(PKT_user_id *uid)
{
- /* List the first attribute as the "user id" */
- if(uid->attribs)
- sprintf( uid->name, "[%s of size %lu]",
- uid->attribs->type==ATTRIB_JPEG?"image":"unknown attribute",
- uid->attribs->len);
+ if(uid->numattribs<=0)
+ sprintf(uid->name,"[bad attribute packet of size %lu]",uid->attrib_len);
+ else if(uid->numattribs>1)
+ sprintf(uid->name,"[%d attributes of size %lu]",
+ uid->numattribs,uid->attrib_len);
else
- sprintf( uid->name, "[bad attribute of size %lu]",
- uid->attrib_len );
+ {
+ /* Only one attribute, so list it as the "user id" */
+
+ if(uid->attribs->type==ATTRIB_IMAGE)
+ {
+ u32 len;
+ byte type;
+
+ if(parse_image_header(uid->attribs,&type,&len))
+ sprintf(uid->name,"[%s image of size %lu]",
+ image_type_to_string(type,1),(ulong)len);
+ else
+ sprintf(uid->name,"[invalid image]");
+ }
+ else
+ sprintf(uid->name,"[unknown attribute of size %lu]",uid->attribs->len);
+ }
uid->len = strlen(uid->name);
}
@@ -1838,7 +1838,7 @@ parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
{
byte *p;
- packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + 50);
+ packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + 70);
setup_user_id(packet);
diff --git a/g10/photoid.c b/g10/photoid.c
index 27ad7fe95..3953e6dbe 100644
--- a/g10/photoid.c
+++ b/g10/photoid.c
@@ -116,7 +116,7 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk)
parse_attribute_subpkts(uid);
make_attribute_uidname(uid);
- show_photo(uid->attribs,pk);
+ show_photos(uid->attribs,uid->numattribs,pk);
switch(cpr_get_answer_yes_no_quit("photoid.jpeg.okay",
_("Is this photo correct (y/N/q)? ")))
{
@@ -147,31 +147,113 @@ PKT_user_id *generate_photo_id(PKT_public_key *pk)
return uid;
}
-void show_photo(const struct user_attribute *attr,PKT_public_key *pk)
+/* Returns 0 for error, 1 for valid */
+int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len)
{
- char *command;
- struct exec_info *spawn;
+ int headerlen;
- /* make command grow */
- command=
- pct_expando(opt.photo_viewer?opt.photo_viewer:DEFAULT_PHOTO_COMMAND,pk);
+ if(attr->len<3)
+ return 0;
- if(!command)
- goto fail;
+ /* For historical reasons (i.e. "oops!"), the header length is
+ little endian. */
+ headerlen=(attr->data[1]<<8) | attr->data[0];
- if(exec_write(&spawn,NULL,command,1,1)!=0)
- goto fail;
+ if(headerlen>attr->len)
+ return 0;
- fwrite(attr->data,attr->len,1,spawn->tochild);
+ if(type && attr->len>=4)
+ {
+ if(attr->data[2]==1) /* header version 1 */
+ *type=attr->data[3];
+ else
+ *type=0;
+ }
+
+ *len=attr->len-headerlen;
+
+ if(*len==0)
+ return 0;
+
+ return 1;
+}
- if(exec_read(spawn)!=0)
+/* style==0 for extension, 1 for name, 2 for MIME type. Remember that
+ the "name" style string could be used in a user ID name field, so
+ make sure it is not too big (see
+ parse-packet.c:parse_attribute). */
+char *image_type_to_string(byte type,int style)
+{
+ char *string;
+
+ switch(type)
{
- exec_finish(spawn);
- goto fail;
+ case 1: /* jpeg */
+ if(style==0)
+ string="jpg";
+ else if(style==1)
+ string="jpeg";
+ else
+ string="image/jpeg";
+ break;
+
+ default:
+ if(style==0)
+ string="bin";
+ else if(style==1)
+ string="unknown";
+ else
+ string="image/x-unknown";
+ break;
}
- if(exec_finish(spawn)!=0)
- goto fail;
+ return string;
+}
+
+void show_photos(const struct user_attribute *attrs,
+ int count,PKT_public_key *pk)
+{
+ int i;
+ struct expando_args args;
+ u32 len;
+
+ memset(&args,0,sizeof(args));
+ args.pk=pk;
+
+ for(i=0;i<count;i++)
+ if(attrs[i].type==ATTRIB_IMAGE &&
+ parse_image_header(&attrs[i],&args.imagetype,&len))
+ {
+ char *command;
+ struct exec_info *spawn;
+ int offset=attrs[i].len-len;
+
+ /* Notice we are not using the byte for image encoding type
+ for more than cosmetics. Most external image viewers can
+ handle a multitude of types, and even if one cannot
+ understand a partcular type, we have no way to know which.
+ The spec specifically permits this, by the way. -dms */
+
+ /* make command grow */
+ command=pct_expando(opt.photo_viewer?
+ opt.photo_viewer:DEFAULT_PHOTO_COMMAND,&args);
+ if(!command)
+ goto fail;
+
+ if(exec_write(&spawn,NULL,command,1,1)!=0)
+ goto fail;
+
+ fwrite(&attrs[i].data[offset],attrs[i].len-offset,1,spawn->tochild);
+
+ if(exec_read(spawn)!=0)
+ {
+ exec_finish(spawn);
+ goto fail;
+ }
+
+ if(exec_finish(spawn)!=0)
+ goto fail;
+ }
return;
diff --git a/g10/photoid.h b/g10/photoid.h
index 0b037304f..ddd36af37 100644
--- a/g10/photoid.h
+++ b/g10/photoid.h
@@ -6,6 +6,8 @@
#include "packet.h"
PKT_user_id *generate_photo_id(PKT_public_key *pk);
-void show_photo(const struct user_attribute *attr,PKT_public_key *pk);
+int parse_image_header(const struct user_attribute *attr,byte *type,u32 *len);
+char *image_type_to_string(byte type,int style);
+void show_photos(const struct user_attribute *attrs,int count,PKT_public_key *pk);
#endif /* !_PHOTOID_H_ */
diff --git a/g10/sign.c b/g10/sign.c
index 29359bda6..f7ddfd847 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -62,6 +62,10 @@ mk_notation_and_policy( PKT_signature *sig, PKT_public_key *pk )
byte *buf;
unsigned n1, n2;
STRLIST nd=NULL,pu=NULL;
+ struct expando_args args;
+
+ memset(&args,0,sizeof(args));
+ args.pk=pk;
/* notation data */
if(IS_SIG(sig) && opt.sig_notation_data)
@@ -124,18 +128,13 @@ mk_notation_and_policy( PKT_signature *sig, PKT_public_key *pk )
{
string = pu->d;
- if(pk)
+ s=pct_expando(string,&args);
+ if(!s)
{
- s=pct_expando(string,pk);
- if(!s)
- {
- log_error(_("WARNING: unable to %%-expand policy url "
- "(too large). Using unexpanded.\n"));
- s=m_strdup(string);
- }
+ log_error(_("WARNING: unable to %%-expand policy url "
+ "(too large). Using unexpanded.\n"));
+ s=m_strdup(string);
}
- else
- s=m_strdup(string);
build_sig_subpkt(sig,SIGSUBPKT_POLICY|
((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0),