📄 pgpkeyiter.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
PGP Key Iteration functions
$Id: pgpKeyIter.c,v 1.28 2002/08/06 20:11:00 dallen Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"
#include "pgpKeyPriv.h"
#include "pgpSigSpec.h"
#include "pgpContext.h"
PGPError
PGPNewKeyIter (
PGPKeyListRef keys,
PGPKeyIterRef * outRef)
{
PGPKeyIter * newIter = NULL;
PGPError err = kPGPError_NoErr;
PGPContextRef context = PGPPeekKeyListContext( keys );
PGPValidatePtr( outRef );
*outRef = NULL;
PGPValidateKeyList( keys );
pgpEnterPGPErrorFunction();
newIter = (PGPKeyIter *)pgpContextMemAlloc(
context, sizeof (PGPKeyIter), kPGPMemoryMgrFlags_Clear );
if ( IsntNull( newIter ) )
{
newIter->magic = kPGPKeyIterMagic;
newIter->nextIterInList = keys->firstIterInList;
newIter->prevIterInList = NULL;
if (newIter->nextIterInList)
newIter->nextIterInList->prevIterInList = newIter;
keys->firstIterInList = newIter;
PGPIncKeyListRefCount(keys);
newIter->keyList = keys;
newIter->keySet = NULL;
newIter->isKeyList = TRUE;
newIter->keyIndex = -1;
newIter->level = -1;
newIter->currentObject = NULL;
*outRef = newIter;
}
else
{
err = kPGPError_OutOfMemory;
}
pgpAssertErrWithPtr( err, *outRef );
return( err );
}
PGPError
PGPNewKeyIterFromKeySet (
PGPKeySetRef keyset,
PGPKeyIterRef * outRef)
{
PGPKeyIter * newIter = NULL;
PGPError err = kPGPError_NoErr;
PGPContextRef context = PGPPeekKeySetContext( keyset );
PGPValidatePtr( outRef );
*outRef = NULL;
PGPValidateKeySet( keyset );
pgpEnterPGPErrorFunction();
newIter = (PGPKeyIter *)pgpContextMemAlloc(
context, sizeof (PGPKeyIter), kPGPMemoryMgrFlags_Clear );
if ( IsntNull( newIter ) )
{
newIter->magic = kPGPKeyIterMagic;
newIter->nextIterInList = NULL;
newIter->prevIterInList = NULL;
PGPIncKeySetRefCount(keyset);
newIter->keyList = NULL;
newIter->keySet = keyset;
newIter->isKeyList = FALSE;
newIter->keyIndex = -1;
newIter->level = -1;
newIter->currentObject = NULL;
*outRef = newIter;
}
else
{
err = kPGPError_OutOfMemory;
}
pgpAssertErrWithPtr( err, *outRef );
return( err );
}
PGPError
PGPNewKeyIterFromKeyDB (
PGPKeyDB * keyDB,
PGPKeyIterRef * outRef)
{
return PGPNewKeyIterFromKeySet( keyDB->rootSet, outRef );
}
PGPError
PGPCopyKeyIter (
PGPKeyIterRef orig,
PGPKeyIterRef * outRef)
{
PGPKeyIterRef newIter = NULL;
PGPError err = kPGPError_NoErr;
PGPValidatePtr( outRef );
*outRef = NULL;
PGPValidateKeyIter( orig );
pgpEnterPGPErrorFunction();
if( orig->isKeyList )
err = PGPNewKeyIter (orig->keyList, &newIter );
else
err = PGPNewKeyIterFromKeySet (orig->keySet, &newIter );
if ( IsntPGPError( err ) )
{
newIter->keyIndex = orig->keyIndex;
newIter->currentObject = orig->currentObject;
newIter->level = orig->level;
*outRef = newIter;
}
pgpAssertErrWithPtr( err, *outRef );
return err;
}
PGPError
PGPFreeKeyIter (PGPKeyIterRef iter)
{
PGPContextRef context = NULL;
PGPValidateKeyIter( iter );
pgpEnterPGPErrorFunction();
context = PGPPeekKeyIterContext( iter );
if( IsntNull(iter->keyList) ) {
if (iter->prevIterInList)
iter->prevIterInList->nextIterInList = iter->nextIterInList;
else
iter->keyList->firstIterInList = iter->nextIterInList;
if (iter->nextIterInList)
iter->nextIterInList->prevIterInList = iter->prevIterInList;
PGPFreeKeyList( iter->keyList );
} else {
PGPFreeKeySet( iter->keySet );
}
iter->magic = ~ iter->magic; /* mark as invalid */
pgpContextMemFree( context, iter);
return( kPGPError_NoErr );
}
PGPInt32
PGPKeyIterIndex (PGPKeyIterRef iter)
{
if ( ! pgpKeyIterIsValid( iter ) )
return( 0 );
pgpEnterZeroFunction();
return iter->keyIndex;
}
static PGPError
pgpKeyIterRewind (PGPKeyIterRef iter)
{
PGPValidateKeyIter( iter );
iter->keyIndex = -1;
iter->level = -1;
iter->currentObject = NULL;
iter->atEndOfLevel = FALSE;
return( kPGPError_NoErr );
}
/* Get the current object or one above us */
static PGPKeyDBObj *
sKeyIterCurrentObject(
PGPKeyIterRef iter,
PGPInt32 level)
{
PGPKeyDBObj *obj;
if( iter->level == level )
{
if( iter->atEndOfLevel )
obj = NULL;
else
obj = iter->currentObject;
} else if( iter->level > level ) {
obj = iter->currentObject;
while( level++ < iter->level ) {
obj = obj->up;
}
} else {
obj = NULL;
}
return obj;
}
/* Returns true if item is a member of the keyiter. If we are based on
* a keylist rather than a keyset, we assume that any key or parent key
* of an object we are called with is in the top level keylist array.
*/
static PGPBoolean
sKeyIterIsMember( PGPKeyIter *iter, PGPKeyDBObj *obj )
{
if( IsNull( obj ) )
return FALSE;
if( !pgpKeyDBObjIsReal( obj ) )
return FALSE;
if( !iter->isKeyList )
return pgpKeySetIsMember( obj, iter->keySet );
if( OBJISTOPKEY( obj ) )
return TRUE;
return PGPKeySetIsMember( obj, iter->keyList->keySet );
}
/* Call with iter pointing at an object at a certain level, and
* advance relOffset steps at that level. Return error if we go too
* far. Should not be used for level 0 if a keylist is used, that
* just steps through the array. Should be used for level 0 on
* keysets, or for level > 0 in all cases. A relOffset of 0 returns
* the current object if it is in the set, or the next object if the
* current one is not in the set. When you first go DOWN to a new level,
* call with relOffset = 0 to find the first object on that level.
*/
static PGPError
sKeyIterMoveAtLevel(
PGPKeyIterRef iter,
PGPInt32 relOffset)
{
PGPKeyDBObj *obj;
PGPKeyDBObj *testobj;
PGPKeyDBObj *prevobj;
if( relOffset >= 0 ) {
/* If at end, can't do any more */
if( iter->atEndOfLevel )
return kPGPError_EndOfIteration;
obj = iter->currentObject;
if( obj == NULL )
return kPGPError_EndOfIteration;
/* Count an extra if current object isn't in set */
if( !sKeyIterIsMember( iter, obj ) && relOffset == 0 )
++relOffset;
/* Advance key relOffset times */
while( relOffset > 0 && IsntNull( obj ) )
{
iter->currentObject = obj;
obj = obj->next;
if(sKeyIterIsMember( iter, obj ) )
--relOffset;
}
if( IsNull( obj ) )
{
iter->atEndOfLevel = TRUE;
return kPGPError_EndOfIteration;
}
iter->currentObject = obj;
iter->atEndOfLevel = FALSE;
return kPGPError_NoErr;
} else {
pgpAssert( relOffset < 0 );
if( IsNull( iter->currentObject ) )
return kPGPError_EndOfIteration;
if( !sKeyIterIsMember( iter, iter->currentObject ) )
{
sKeyIterMoveAtLevel( iter, 0 );
}
obj = iter->currentObject;
pgpAssert( (obj == NULL) || sKeyIterIsMember( iter, obj ) );
/* Scan from beginning, -relOffset times */
/* Or if we find obj before then, we move back to beginning */
/* Find first obj in set as testobj */
if( iter->level == 0 )
{
PGPKeyDBRef kdb = PGPPeekKeyDBObjKeyDB( obj );
testobj = kdb->firstKeyInDB;
} else {
testobj = obj->up->down;
}
while( IsntNull(testobj) && !sKeyIterIsMember( iter, testobj ) )
testobj = testobj->next;
/* There may be no objects at this level */
if( IsNull( testobj ) )
return kPGPError_EndOfIteration;
/* testobj is now first obj in set at this level */
prevobj = testobj;
/* Advance testobj -relOffset times, abort if find key */
while( relOffset < 0 && testobj != obj )
{
testobj = testobj->next;
if(sKeyIterIsMember( iter, testobj ) )
++relOffset;
}
/* If hit key before then, return error */
if( relOffset < 0 ) {
/* Set pointer to starting object */
iter->currentObject = prevobj;
iter->atEndOfLevel = FALSE;
return kPGPError_EndOfIteration;
}
/* Advance testobj forward until we hit obj, in step with prevobj */
while( testobj != obj ) {
do {
testobj = testobj->next;
} while(!sKeyIterIsMember( iter, testobj ) );
do {
prevobj = prevobj->next;
} while(!sKeyIterIsMember( iter, prevobj ) );
}
iter->currentObject = prevobj;
iter->atEndOfLevel = FALSE;
}
return kPGPError_NoErr;
}
/* Move the current top-level key by the specified offset */
static PGPError
sKeyIterMove(
PGPKeyIterRef iter,
PGPInt32 relOffset)
{
PGPKeyDBRef kdb;
long newOffset;
PGPKeyListRef keylist = NULL;
PGPError err = kPGPError_NoErr;
if( relOffset == 0 )
return kPGPError_NoErr;
if( iter->isKeyList )
{
pgpAssert( IsntNull( iter->keyList ) );
keylist = iter->keyList;
newOffset = iter->keyIndex + relOffset;
#if 0
/* Check for removed key */
if ( IsntNull( iter->currentObject ) && iter->keyIndex >= 0 &&
( iter->keyIndex >= keylist->keyCount-1 ||
keylist->keys[iter->keyIndex] != iter->currentObject ) )
{
/* key removed from keylist */
if (relOffset == 0)
{
/* pgpFixBeforeShip( "this is probably wrong" ); */
err = kPGPError_EndOfIteration;
return( err );
}
else if (relOffset > 0)
newOffset--;
}
#endif
iter->level = 0;
if (newOffset >= 0 && newOffset < keylist->keyCount)
{
iter->currentObject = keylist->keys[newOffset];
iter->atEndOfLevel = FALSE;
iter->keyIndex = newOffset;
}
else
{
iter->atEndOfLevel = TRUE;
newOffset = keylist->keyCount - 1;
iter->keyIndex = newOffset;
iter->currentObject = keylist->keys[newOffset];
err = kPGPError_EndOfIteration;
}
}
else
{
pgpAssert( IsntNull( iter->keySet ) );
kdb = iter->keySet->keyDB;
/* Move up to key we are currently pointing at */
if( iter->level < 0 ) {
iter->currentObject = kdb->firstKeyInDB;
if( IsNull( iter->currentObject ) )
return kPGPError_EndOfIteration;
--relOffset; /* Find first key that matches */
iter->level = 0;
} else if( iter->level > 0 ) {
while( iter->level ) {
iter->currentObject = iter->currentObject->up;
--iter->level;
iter->atEndOfLevel = FALSE;
}
}
pgpAssert( iter->level <= 0 );
pgpAssert( IsntNull(iter->currentObject) );
err = sKeyIterMoveAtLevel( iter, relOffset );
if( IsntPGPError( err ) )
iter->keyIndex += relOffset; /* approximate this */
}
return err;
}
PGPInt32
PGPKeyIterSeek (PGPKeyIterRef iter, PGPKeyDBObjRef key)
{
PGPKeyDBObj **keys;
long i;
PGPValidateKeyIter( iter );
PGPValidateKey( key );
pgpEnterZeroFunction();
iter->keyIndex = -1;
iter->currentObject = NULL;
iter->level = -1;
if( iter->isKeyList ) {
keys = iter->keyList->keys;
if (iter->keyList && (keys = iter->keyList->keys) != NULL) {
for (i = 0; i < iter->keyList->keyCount; i++) {
if (keys[i] == key) {
iter->keyIndex = i;
iter->currentObject = key;
iter->level = 0;
iter->atEndOfLevel = FALSE;
break;
}
}
}
} else {
pgpKeyIterRewind( iter );
while( iter->currentObject != key ) {
if( IsPGPError( sKeyIterMove( iter, 1 ) ) ) {
iter->keyIndex = -1;
iter->level = -1;
iter->currentObject = NULL;
iter->atEndOfLevel = FALSE;
break;
}
}
}
return iter->keyIndex;
}
PGPError
PGPKeyIterMove (
PGPKeyIterRef iter,
PGPInt32 relOffset,
PGPKeyDBObjRef * outRef )
{
PGPError err = kPGPError_NoErr;
PGPValidateKeyIter( iter );
pgpAssertAddrValid( outRef, PGPKeyDBRef );
PGPValidatePtr( outRef );
*outRef = NULL;
PGPValidateKeyIter( iter );
pgpEnterPGPErrorFunction();
err = sKeyIterMove( iter, relOffset );
if( IsntPGPError( err ) )
*outRef = iter->currentObject;
return err;
}
static PGPError
pgpKeyIterNext (
PGPKeyIterRef iter,
PGPKeyDBObjRef * outRef)
{
PGPError err;
err = PGPKeyIterMove(iter, 1, outRef );
pgpAssertErrWithPtr( err, *outRef );
return( err );
}
static PGPError
pgpKeyIterPrev (
PGPKeyIterRef iter,
PGPKeyDBObjRef * outRef)
{
PGPError err;
err = PGPKeyIterMove( iter, -1, outRef);
pgpAssertErrWithPtr( err, *outRef );
return( err );
}
/* Get next object irrespective of level */
PGPError
pgpKeyIterNextObject (
PGPKeyIterRef iter,
PGPKeyDBObjRef * outRef)
{
PGPKeyDBObj *obj;
PGPError err = kPGPError_NoErr;
PGPValidatePtr( outRef );
*outRef = NULL;
PGPValidateKeyIter( iter );
if( iter->level < 0 ) {
/* Before first object, move forward to it */
return PGPKeyIterMove( iter, 1, outRef );
}
obj = iter->currentObject;
if( !OBJISSIG( obj ) && IsntNull( obj->down ) ) {
/* Move down if possible */
++iter->level;
iter->currentObject = obj->down;
if( IsntPGPError(err = sKeyIterMoveAtLevel( iter, 0 ) ) )
{
*outRef = iter->currentObject;
return kPGPError_NoErr;
}
}
while( iter->level >= 0 )
{
if( iter->level == 0 )
return PGPKeyIterMove( iter, 1, outRef );
err = sKeyIterMoveAtLevel( iter, 1 );
if( IsntPGPError( err ) )
{
*outRef = iter->currentObject;
return kPGPError_NoErr;
}
/* Can't go any farther, go up a level */
pgpAssert( iter->level > 0 );
--iter->level;
iter->currentObject = iter->currentObject->up;
iter->atEndOfLevel = FALSE;
}
pgpAssert( 0 );
return( err );
}
static PGPError
pgpKeyIterKey (
PGPKeyIterRef iter,
PGPKeyDBObjRef * outRef)
{
PGPKeyDBObj *key;
PGPError err = kPGPError_NoErr;
pgpAssertAddrValid( outRef, PGPKeyDBRef );
PGPValidatePtr( outRef );
*outRef = NULL;
PGPValidateKeyIter( iter );
/* Should be a move(0) ? */
key = sKeyIterCurrentObject( iter, 0 );
/* pgpFixBeforeShip( "what if key has been deleted" ) */
if ( IsNull( key ) )
{
err = kPGPError_EndOfIteration;
}
*outRef = key;
return err;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -