diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/ChangeLog | 21 | ||||
-rw-r--r-- | g10/gpgv.c | 6 | ||||
-rw-r--r-- | g10/keyedit.c | 56 | ||||
-rw-r--r-- | g10/keylist.c | 6 | ||||
-rw-r--r-- | g10/main.h | 9 | ||||
-rw-r--r-- | g10/misc.c | 147 | ||||
-rw-r--r-- | g10/packet.h | 8 | ||||
-rw-r--r-- | g10/parse-packet.c | 50 | ||||
-rw-r--r-- | g10/photoid.c | 116 | ||||
-rw-r--r-- | g10/photoid.h | 4 | ||||
-rw-r--r-- | g10/sign.c | 19 |
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), |