📄 pgpkeylist.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
PGPKeyList implementation
$Id: pgpKeyList.c,v 1.16 2002/08/06 20:11:00 dallen Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <string.h>
#include <ctype.h>
#include "pgpTypes.h"
#include "pgpDebug.h"
#include "pgpKeyPriv.h"
#include "pgpMem.h"
#include "pgpTimeDate.h"
#include "pgpUsuals.h"
#include "pgpMemPool.h"
#include "pgpContext.h"
#include "pgpOptionListPriv.h"
static int
keyCompareByKeyID(void const *a, void const *b)
{
PGPKeyDBObj * keyA = *(PGPKeyDBObj **)a;
PGPKeyDBObj * keyB = *(PGPKeyDBObj **)b;
PGPKeyID rawA;
PGPKeyID rawB;
int result = 1;
pgpKeyID8( keyA, NULL, &rawA );
pgpKeyID8( keyB, NULL, &rawB );
result = PGPCompareKeyIDs( &rawA, &rawB);
return( result );
}
static int
keyCompareByReverseKeyID(void const *a, void const *b)
{
return -keyCompareByKeyID(a, b);
}
PGPInt32
PGPCompareUserIDStrings(char const *a, char const *b)
{
pgpEnterZeroFunction();
pgpAssert( IsntNull( a ) );
pgpAssert( IsntNull( b ) );
if ( IsNull( a ) || IsNull( b ) )
return( 0 );
for (;;)
{
while (*a && tolower(*a) == tolower(*b))
a++, b++;
while (*a && !isalnum(*a))
a++;
while (*b && !isalnum(*b))
b++;
if (!*a || tolower(*a) != tolower(*b))
break;
a++;
b++;
}
return (uchar)tolower(*a) - (uchar)tolower(*b);
}
static int
keyCompareByUserID(void const *a, void const *b)
{
PGPKeyDBObj * keyA = *(PGPKeyDBObj **)a;
PGPKeyDBObj * keyB = *(PGPKeyDBObj **)b;
char nameA[ kPGPMaxUserIDSize ];
char nameB[ kPGPMaxUserIDSize ];
int compareResult = 0;
PGPSize actualLength;
/* if we get an error, it's OK; we'll just end up comparing the first
256 bytes */
(void)PGPGetPrimaryUserIDName( keyA, nameA, sizeof( nameA ),
&actualLength );
(void)PGPGetPrimaryUserIDName( keyB, nameB, sizeof( nameB ),
&actualLength );
compareResult = PGPCompareUserIDStrings(nameA, nameB);
if ( compareResult == 0 )
compareResult = keyCompareByKeyID(a, b);
return compareResult;
}
static int
keyCompareByReverseUserID(void const *a, void const *b)
{
return -keyCompareByUserID(a, b);
}
static int
keyCompareByValidity(void const *a, void const *b)
{
PGPKeyDBObj * keyA = *(PGPKeyDBObj **)a;
PGPKeyDBObj * keyB = *(PGPKeyDBObj **)b;
PGPValidity validityA;
PGPValidity validityB;
PGPError result;
result = PGPGetPrimaryUserIDValidity(keyA, &validityA);
pgpAssert(result == kPGPError_NoErr);
result = PGPGetPrimaryUserIDValidity(keyB, &validityB);
pgpAssert(result == kPGPError_NoErr);
if (validityA < validityB)
return 1;
else if (validityA > validityB)
return -1;
else
return keyCompareByKeyID(a, b);
}
static int
keyCompareByReverseValidity(void const *a, void const *b)
{
return -keyCompareByValidity(a, b);
}
static int
keyCompareByTrust(void const *a, void const *b)
{
PGPKeyDBObj * keyA = *(PGPKeyDBObj **)a;
PGPKeyDBObj * keyB = *(PGPKeyDBObj **)b;
PGPInt32 trustA;
PGPInt32 trustB;
PGPError result;
result = pgpGetKeyNumber(keyA, kPGPKeyProperty_Trust, &trustA);
pgpAssert(result == kPGPError_NoErr);
result = pgpGetKeyNumber(keyB, kPGPKeyProperty_Trust, &trustB);
pgpAssert(result == kPGPError_NoErr);
if (trustA < trustB)
return 1;
else if (trustA > trustB)
return -1;
else
return keyCompareByKeyID(a, b);
}
static int
keyCompareByReverseTrust(void const *a, void const *b)
{
return -keyCompareByTrust(a, b);
}
static int
keyCompareByEncryptKeySize(void const *a, void const *b)
{
PGPKeyDBObj * keyA = *(PGPKeyDBObj **)a;
PGPKeyDBObj * keyB = *(PGPKeyDBObj **)b;
PGPKeyDBObj * subKeyA = NULL;
PGPKeyDBObj * subKeyB = NULL;
PGPInt32 keySizeA;
PGPInt32 keySizeB;
PGPError err;
err = pgpGetFirstSubKey(keyA, &subKeyA);
if ( IsntPGPError( err ) )
err = pgpGetSubKeyNumber(subKeyA, kPGPSubKeyProperty_Bits, &keySizeA);
else
err = pgpGetKeyNumber(keyA, kPGPKeyProperty_Bits, &keySizeA);
pgpAssertNoErr( err );
err = pgpGetFirstSubKey(keyB, &subKeyB);
if ( IsntPGPError( err ) )
err = pgpGetSubKeyNumber(subKeyB, kPGPSubKeyProperty_Bits, &keySizeB);
else
err = pgpGetKeyNumber(keyB, kPGPKeyProperty_Bits, &keySizeB);
pgpAssertNoErr( err );
if (keySizeA < keySizeB)
return 1;
else if (keySizeA > keySizeB)
return -1;
return keyCompareByKeyID(a, b);
}
static int
keyCompareByReverseEncryptKeySize(void const *a, void const *b)
{
return -keyCompareByEncryptKeySize(a, b);
}
static int
keyCompareBySigKeySize(void const *a, void const *b)
{
PGPKeyDBObj * keyA = *(PGPKeyDBObj **)a;
PGPKeyDBObj * keyB = *(PGPKeyDBObj **)b;
PGPInt32 keySizeA;
PGPInt32 keySizeB;
PGPError result;
result = pgpGetKeyNumber(keyA, kPGPKeyProperty_Bits, &keySizeA);
pgpAssert(result == kPGPError_NoErr);
result = pgpGetKeyNumber(keyB, kPGPKeyProperty_Bits, &keySizeB);
pgpAssert(result == kPGPError_NoErr);
if (keySizeA < keySizeB)
return 1;
else if (keySizeA > keySizeB)
return -1;
else
return keyCompareByKeyID(a, b);
}
static int
keyCompareByReverseSigKeySize(void const *a, void const *b)
{
return -keyCompareBySigKeySize(a, b);
}
static int
keyCompareByCreation(void const *a, void const *b)
{
PGPKeyDBObj * keyA = *(PGPKeyDBObj **)a;
PGPKeyDBObj * keyB = *(PGPKeyDBObj **)b;
PGPTime creationA;
PGPTime creationB;
PGPError result;
result = pgpGetKeyTime(keyA, kPGPKeyProperty_Creation, &creationA);
pgpAssert(result == kPGPError_NoErr);
result = pgpGetKeyTime(keyB, kPGPKeyProperty_Creation, &creationB);
pgpAssert(result == kPGPError_NoErr);
if (creationA < creationB)
return 1;
else if (creationA > creationB)
return -1;
else
return keyCompareByKeyID(a, b);
}
static int
keyCompareByReverseCreation(void const *a, void const *b)
{
return -keyCompareByCreation(a, b);
}
static int
keyCompareByExpiration(void const *a, void const *b)
{
PGPKeyDBObj * keyA = *(PGPKeyDBObj **)a;
PGPKeyDBObj * keyB = *(PGPKeyDBObj **)b;
PGPTime expirationA;
PGPTime expirationB;
PGPError result;
result = pgpGetKeyTime(keyA, kPGPKeyProperty_Expiration, &expirationA);
pgpAssert(result == kPGPError_NoErr);
result = pgpGetKeyTime(keyB, kPGPKeyProperty_Expiration, &expirationB);
pgpAssert(result == kPGPError_NoErr);
if (expirationA == expirationB)
return keyCompareByKeyID(a, b);
else if (expirationA == kPGPExpirationTime_Never)
return -1;
else if (expirationB == kPGPExpirationTime_Never)
return 1;
else if (expirationA < expirationB)
return 1;
else /* expirationA > expirationB */
return -1;
}
static int
keyCompareByReverseExpiration(void const *a, void const *b)
{
return -keyCompareByExpiration(a, b);
}
typedef int (*CompareFunc)(void const *, void const *);
static const CompareFunc compareFunc[] = {
NULL,
NULL,
NULL,
NULL,
keyCompareByUserID,
keyCompareByReverseUserID,
keyCompareByKeyID,
keyCompareByReverseKeyID,
keyCompareByValidity,
keyCompareByReverseValidity,
keyCompareByTrust,
keyCompareByReverseTrust,
keyCompareByEncryptKeySize,
keyCompareByReverseEncryptKeySize,
keyCompareBySigKeySize,
keyCompareByReverseSigKeySize,
keyCompareByCreation,
keyCompareByReverseCreation,
keyCompareByExpiration,
keyCompareByReverseExpiration,
};
#if PGP_DEBUG
static PGPKeyOrdering sNumCompareFuncs = (PGPKeyOrdering)
(sizeof(compareFunc) / sizeof(compareFunc[0]));
#endif
PGPInt32
PGPCompareKeys(PGPKeyDBObj *a, PGPKeyDBObj *b, PGPKeyOrdering order)
{
pgpEnterZeroFunction();
pgpa((
pgpaPGPKeyValid(a),
pgpaPGPKeyValid(b),
pgpaAssert(order > 0 && (2*order) < sNumCompareFuncs
&& order != kPGPKeyOrdering_Any)));
if ( ! ( pgpKeyIsValid( a ) && pgpKeyIsValid( b ) ) )
return( 0 );
return (*compareFunc[2*order])(&a, &b);
}
static void
sortKeyList(PGPKeyList *list)
{
pgpa((
pgpaPGPKeyListValid(list),
pgpaAssert(list->order > 0 && 2*list->order < sNumCompareFuncs)));
if (list->order != kPGPKeyOrdering_Any)
qsort(list->keys, list->keyCount, sizeof(list->keys[0]),
compareFunc[2*list->order+list->reverse]);
}
#if 0
/*
* Keep in mind that the comparison functions are not guaranteed to
* be total orderings, and so even if an element of the list has a
* perfect match with <key>, the index returned might not contain a
* perfect match.
*/
static long
binarySearchKeyList(PGPKeyList *list, PGPKeyDBObj *key)
{
long lo;
long hi;
long i;
int result;
int (*compare)(void const *, void const *);
pgpa((
pgpaPGPKeyListValid(list),
pgpaPGPKeyValid(key),
pgpaAssert(list->order > 0 && 2*list->order < sNumCompareFuncs)));
if (list->order == kPGPKeyOrdering_Any)
return list->keyCount;
compare = compareFunc[2*list->order+list->reverse];
lo = 0;
hi = list->keyCount;
while (lo < hi)
{
i = (lo + hi) / 2;
result = (*compare)(&key, &list->keys[i]);
if (result > 0)
lo = i + 1;
else if (result < 0)
hi = i;
else
return i;
}
return lo;
}
#endif
PGPError
PGPOrderKeySet(
PGPKeySet * keys,
PGPKeyOrdering order,
PGPBoolean reverse,
PGPKeyListRef * outRef )
{
PGPKeyList * list;
PGPKeyDBObj * key;
PGPUInt32 count;
PGPUInt32 i;
PGPError err = kPGPError_NoErr;
PGPContextRef context = PGPPeekKeySetContext( keys );
PGPValidatePtr( outRef );
*outRef = NULL;
PGPValidateKeySet( keys );
pgpEnterPGPErrorFunction();
/* list = pgpNew(PGPKeyList); */
list = (PGPKeyList *)pgpContextMemAlloc( context,
sizeof(PGPKeyList), kPGPMemoryMgrFlags_Clear );
if (list == NULL)
return kPGPError_OutOfMemory;
list->magic = kPGPKeyListMagic;
(void)PGPCountKeys(keys, &count );
list->keyCount = count;
list->keys = (PGPKeyDBObj **)pgpContextMemAlloc( context,
count * sizeof(PGPKeyDBObj *), kPGPMemoryMgrFlags_Clear);
if (list->keys == NULL)
{
pgpContextMemFree( context, list);
return kPGPError_OutOfMemory;
}
list->refCount = 1;
list->keySet = keys;
list->order = order;
list->reverse = reverse?1:0;
list->prevListInSet = NULL;
list->nextListInSet = keys->firstListInSet;
if( IsntNull( list->nextListInSet ) )
list->nextListInSet->prevListInSet = list;
keys->firstListInSet = list;
list->firstIterInList = NULL;
PGPIncKeySetRefCount(keys);
i = 0;
for (key = keys->keyDB->firstKeyInDB; key; key = key->next)
{
pgpa(pgpaPGPKeyValid(key));
if( !pgpKeyDBObjIsReal(key) )
continue;
if (pgpKeySetIsMember( key, keys ))
{
pgpAssert(i < count);
list->keys[i++] = key;
}
}
pgpAssert(i == count);
sortKeyList(list);
*outRef = list;
return( err );
}
/* Call this to recalculate the list contents */
PGPError
pgpUpdateList(PGPKeyList *list)
{
PGPKeySet * keys;
PGPKeyDBObj * key;
void * vkeys;
PGPUInt32 count;
PGPUInt32 i;
PGPError err = kPGPError_NoErr;
PGPContextRef context;
PGPValidateKeyList( list );
/* Pick up fields from list */
keys = list->keySet;
context = PGPPeekKeySetContext( keys );
/* Reallocate array */
(void)PGPCountKeys(keys, &count );
vkeys = (void *)list->keys;
err = pgpContextMemRealloc( context, &vkeys,
count * sizeof(PGPKeyDBObj *), kPGPMemoryMgrFlags_Clear);
if (IsPGPError( err ))
return err;
list->keys = (PGPKeyDBObj **)vkeys;
list->keyCount = count;
i = 0;
for (key = keys->keyDB->firstKeyInDB; key; key = key->next)
{
pgpa(pgpaPGPKeyValid(key));
if( !pgpKeyDBObjIsReal(key) )
continue;
if (pgpKeySetIsMember( key, keys ))
{
pgpAssert(i < count);
list->keys[i++] = key;
}
}
pgpAssert(i == count);
sortKeyList(list);
return( err );
}
PGPError
PGPIncKeyListRefCount(PGPKeyList *list)
{
PGPValidateKeyList( list );
pgpEnterPGPErrorFunction();
list->refCount++;
return( kPGPError_NoErr );
}
PGPError
PGPFreeKeyList(PGPKeyList *list)
{
PGPContextRef context = NULL;
PGPValidateKeyList( list );
pgpEnterPGPErrorFunction();
context = PGPPeekKeyListContext( list );
list->refCount--;
if (list->refCount <= 0)
{
list->magic = ~ list->magic; /* mark as invalid */
if (list->prevListInSet)
list->prevListInSet->nextListInSet = list->nextListInSet;
else
list->keySet->firstListInSet = list->nextListInSet;
if (list->nextListInSet)
list->nextListInSet->prevListInSet = list->prevListInSet;
pgpAssert(list->firstIterInList == NULL);
pgpContextMemFree( context, list->keys);
PGPFreeKeySet(list->keySet);
pgpContextMemFree( context, list);
}
return( kPGPError_NoErr );
}
PGPBoolean
pgpKeyListIsValid( PGPKeyList const * keyList)
{
return( IsntNull( keyList ) && keyList->magic == kPGPKeyListMagic );
}
#if PGP_DEBUG /* [ */
PGPBoolean
pgpaInternalPGPKeyListValid(
pgpaCallPrefixDef,
PGPKeyList const * keyList,
char const * varName)
{
pgpaAddrValid(keyList, PGPKeyList);
pgpaFailIf(keyList->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));
pgpaFmtMsg((pgpaFmtPrefix,
"pgpaPGPKeyListValid failed on %s (%p)", varName, keyList));
return pgpaFailed;
}
#endif /* ] PGP_DEBUG */
/*
* Local Variables:
* tab-width: 4
* End:
* vi: ts=4 sw=4
* vim: si
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -