1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-09 12:54:23 +01:00

* import.c (collapse_uids): Significant speedup for de-duping user

IDs.
This commit is contained in:
David Shaw 2007-09-02 14:09:24 +00:00
parent d1a13319bb
commit 8bc8b9d932
2 changed files with 87 additions and 70 deletions

View File

@ -1,3 +1,8 @@
2007-09-02 David Shaw <dshaw@jabberwocky.com>
* import.c (collapse_uids): Significant speedup for de-duping user
IDs.
2007-08-24 Werner Koch <wk@g10code.com> 2007-08-24 Werner Koch <wk@g10code.com>
* keyring.c (keyring_register_filename): Use same_file_p. * keyring.c (keyring_register_filename): Use same_file_p.

View File

@ -1644,90 +1644,102 @@ delete_inv_parts( const char *fname, KBNODE keyblock,
* It may happen that the imported keyblock has duplicated user IDs. * It may happen that the imported keyblock has duplicated user IDs.
* We check this here and collapse those user IDs together with their * We check this here and collapse those user IDs together with their
* sigs into one. * sigs into one.
* Returns: True if the keyblock hash changed. * Returns: True if the keyblock has changed.
*/ */
int int
collapse_uids( KBNODE *keyblock ) collapse_uids( KBNODE *keyblock )
{ {
KBNODE n, n2; KBNODE uid1;
int in_uid; int any=0;
int any=0;
restart: for(uid1=*keyblock;uid1;uid1=uid1->next)
for( n = *keyblock; n; n = n->next ) { {
if( n->pkt->pkttype != PKT_USER_ID ) KBNODE uid2;
if(uid1->pkt->pkttype!=PKT_USER_ID)
continue;
for(uid2=uid1->next;uid2;uid2=uid2->next)
{
if(uid2->pkt->pkttype!=PKT_USER_ID)
continue; continue;
for( n2 = n->next; n2; n2 = n2->next ) {
if( n2->pkt->pkttype == PKT_USER_ID if(cmp_user_ids(uid1->pkt->pkt.user_id,
&& !cmp_user_ids( n->pkt->pkt.user_id, uid2->pkt->pkt.user_id)==0)
n2->pkt->pkt.user_id ) ) { {
/* found a duplicate */ /* We have a duplicated uid */
any = 1; KBNODE sig1,last;
if( !n2->next
|| n2->next->pkt->pkttype == PKT_USER_ID any=1;
|| n2->next->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| n2->next->pkt->pkttype == PKT_SECRET_SUBKEY ) { /* Now take uid2's signatures, and attach them to
/* no more signatures: delete the user ID uid1 */
* and start over */ for(last=uid2;last->next;last=last->next)
remove_kbnode( keyblock, n2 ); {
if(last->next->pkt->pkttype==PKT_USER_ID
|| last->next->pkt->pkttype==PKT_PUBLIC_SUBKEY
|| last->next->pkt->pkttype==PKT_SECRET_SUBKEY)
break;
} }
else {
/* The simple approach: Move one signature and /* Snip out uid2 */
* then start over to delete the next one :-( */ (find_prev_kbnode(*keyblock,uid2,0))->next=last->next;
move_kbnode( keyblock, n2->next, n->next );
/* Now put uid2 in place as part of uid1 */
last->next=uid1->next;
uid1->next=uid2;
remove_kbnode(keyblock,uid2);
/* Now dedupe uid1 */
for(sig1=uid1->next;sig1;sig1=sig1->next)
{
KBNODE sig2;
if(sig1->pkt->pkttype==PKT_USER_ID
|| sig1->pkt->pkttype==PKT_PUBLIC_SUBKEY
|| sig1->pkt->pkttype==PKT_SECRET_SUBKEY)
break;
if(sig1->pkt->pkttype!=PKT_SIGNATURE)
continue;
for(sig2=sig1->next,last=sig1;sig2;last=sig2,sig2=sig2->next)
{
if(sig2->pkt->pkttype==PKT_USER_ID
|| sig2->pkt->pkttype==PKT_PUBLIC_SUBKEY
|| sig2->pkt->pkttype==PKT_SECRET_SUBKEY)
break;
if(sig2->pkt->pkttype!=PKT_SIGNATURE)
continue;
if(cmp_signatures(sig1->pkt->pkt.signature,
sig2->pkt->pkt.signature)==0)
{
/* We have a match, so delete the second
signature */
remove_kbnode(&uid1,sig2);
sig2=last;
}
}
} }
goto restart;
} }
} }
} }
if( !any )
return 0;
restart_sig: if(any && !opt.quiet)
/* now we may have duplicate signatures on one user ID: fix this */ {
for( in_uid = 0, n = *keyblock; n; n = n->next ) { const char *key="???";
if( n->pkt->pkttype == PKT_USER_ID )
in_uid = 1; if( (uid1=find_kbnode( *keyblock, PKT_PUBLIC_KEY )) )
else if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY key=keystr_from_pk(uid1->pkt->pkt.public_key);
|| n->pkt->pkttype == PKT_SECRET_SUBKEY ) else if( (uid1 = find_kbnode( *keyblock, PKT_SECRET_KEY )) )
in_uid = 0; key=keystr_from_sk(uid1->pkt->pkt.secret_key);
else if( in_uid ) {
n2 = n; log_info(_("key %s: duplicated user ID detected - merged\n"),key);
do {
KBNODE ncmp = NULL;
for( ; n2; n2 = n2->next ) {
if( n2->pkt->pkttype == PKT_USER_ID
|| n2->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| n2->pkt->pkttype == PKT_SECRET_SUBKEY )
break;
if( n2->pkt->pkttype != PKT_SIGNATURE )
;
else if( !ncmp )
ncmp = n2;
else if( !cmp_signatures( ncmp->pkt->pkt.signature,
n2->pkt->pkt.signature )) {
remove_kbnode( keyblock, n2 );
goto restart_sig;
}
}
n2 = ncmp? ncmp->next : NULL;
} while( n2 );
}
} }
if(!opt.quiet) return any;
{
const char *key="???";
if( (n = find_kbnode( *keyblock, PKT_PUBLIC_KEY )) )
key=keystr_from_pk(n->pkt->pkt.public_key);
else if( (n = find_kbnode( *keyblock, PKT_SECRET_KEY )) )
key=keystr_from_sk(n->pkt->pkt.secret_key);
log_info(_("key %s: duplicated user ID detected - merged\n"),key);
}
return 1;
} }
/* Check for a 0x20 revocation from a revocation key that is not /* Check for a 0x20 revocation from a revocation key that is not