📄 pgpoptionlist.c
字号:
/*____________________________________________________________________________
pgpOptionList.c
Copyright (C) 1997 Network Associates Inc. and affiliated companies.
All rights reserved.
$Id: pgpOptionList.c,v 1.68 1999/03/10 02:53:58 heller Exp $
____________________________________________________________________________*/
#include <string.h>
#include "pgpFileSpec.h"
#include "pgpContext.h"
#include "pgpOptionList.h"
#include "pgpEncodePriv.h"
#include "pgpErrors.h"
#if PGP_CLIENT_LIBRARY
#include "pgpClientLib.h" /* No PFL dependencies for client library */
#else
#include "pgpDebug.h"
#include "pgpMem.h"
#endif
enum
{
kPGPOptionList_Magic = 0x4F4C7374, /* 'OLst' */
kPGPOptionList_MajorVersion = 1,
kPGPOptionList_MinorVersion = 1,
kPGPOptionList_NumGrowElements = 5
};
enum
{
kPGPOptionListFlag_PersistentList = ( 1 << 0 )
};
struct PGPOptionList
{
PGPUInt32 magic; /* Always kPGPOptionList_Magic */
PGPVersion version;
PGPContextRef context;
PGPError err; /* Important that this field is second */
PGPFlags flags;
PGPUInt16 maxOptions;
PGPUInt16 numOptions;
PGPOption *options;
};
PGPBoolean
pgpOptionListIsReal(PGPOptionListRef optionList)
{
return( optionList != kPGPEndOfArgsOptionListRef &&
optionList != kPGPOutOfMemoryOptionListRef &&
optionList != kPGPBadParamsOptionListRef &&
optionList != kPGPNullOptionListRef );
}
PGPError
pgpOptionListToError( PGPOptionListRef optionList )
{
PGPError err = kPGPError_NoErr;
if ( optionList == kPGPEndOfArgsOptionListRef ||
optionList == kPGPBadParamsOptionListRef ||
optionList == kPGPNullOptionListRef )
{
err = kPGPError_BadParams;
}
else if ( optionList == kPGPOutOfMemoryOptionListRef )
{
err = kPGPError_OutOfMemory;
}
else
{
pgpAssert( pgpOptionListIsReal( optionList ) );
err = kPGPError_NoErr;
}
return( err );
}
static PGPBoolean
pgpVerifyOptionList(PGPOptionListRef optionList)
{
PGPBoolean isValid = TRUE;
if( pgpOptionListIsReal( optionList ) )
{
if( optionList->numOptions <= optionList->maxOptions )
{
PGPUInt32 optionIndex;
for( optionIndex = 0; optionIndex < optionList->numOptions;
++optionIndex )
{
const PGPOption *curOption;
curOption = &optionList->options[optionIndex];
if( ( (PGPInt32) curOption->type >=
kPGPOptionType_FirstSDKOption &&
curOption->type < kPGPOptionType_LastSDKOption ) ||
( curOption->type >= kPGPOptionType_FirstUIOption &&
curOption->type < kPGPOptionType_LastUIOption ) ||
( curOption->type >= kPGPOptionType_FirstNetOption &&
curOption->type < kPGPOptionType_LastNetOption ) )
{
/* OK */
}
else
{
isValid = FALSE;
break;
}
if( PGPOptionListRefIsValid( curOption->subOptions ) )
{
isValid = pgpVerifyOptionList( curOption->subOptions );
if( ! isValid )
break;
}
}
}
else
{
isValid = FALSE;
}
}
return( isValid );
}
/*____________________________________________________________________________
This function validates a PGPOptionList data structure. It does not assert
so it can be used within assert macros.
____________________________________________________________________________*/
PGPBoolean
pgpOptionListIsValid(PGPOptionListRef optionList)
{
PGPBoolean isValid;
if( pgpOptionListIsReal( optionList ) )
{
isValid = ( optionList != NULL &&
optionList->magic == kPGPOptionList_Magic );
#if PGP_DEBUG /* [ */
if( isValid )
{
/* Perform more stringent check */
isValid = pgpVerifyOptionList( optionList );
}
#endif /* ] */
}
else
{
isValid = TRUE;
}
return( isValid );
}
PGPError
pgpGetOptionListError(PGPOptionListRef optionList)
{
PGPError err;
PGPValidateParam( pgpOptionListIsValid( optionList ) );
if( optionList == kPGPEndOfArgsOptionListRef ||
optionList == kPGPNullOptionListRef )
{
err = kPGPError_NoErr;
}
else if( optionList == kPGPOutOfMemoryOptionListRef )
{
err = kPGPError_OutOfMemory;
}
else if( optionList == kPGPBadParamsOptionListRef )
{
err = kPGPError_BadParams;
}
else
{
err = optionList->err;
}
return( err );
}
PGPUInt32
pgpGetOptionListCount(PGPOptionListRef optionList)
{
pgpAssert( pgpOptionListIsValid( optionList ) );
return( optionList->numOptions );
}
void
pgpSetOptionListError(
PGPOptionListRef optionList,
PGPError err)
{
pgpAssert( pgpOptionListIsValid( optionList ) );
if( pgpOptionListIsReal( optionList ) )
{
/* Set the err code iff there isn't already an err for the list */
if( IsntPGPError( optionList->err ) )
{
optionList->err = err;
}
}
}
static void
pgpFreeOptionListInternal(
PGPOptionListRef optionList,
PGPBoolean freePersistentList)
{
pgpAssert( pgpOptionListIsValid( optionList ) );
if( pgpOptionListIsReal( optionList ) )
{
PGPBoolean freeTheList = TRUE;
if( ( optionList->flags & kPGPOptionListFlag_PersistentList ) != 0 )
{
freeTheList = freePersistentList;
}
if( freeTheList )
{
PGPUInt32 optionIndex;
/*
** Free all of the allocations and suboption lists hanging
** off of the main option list
*/
for( optionIndex = 0; optionIndex < optionList->numOptions;
optionIndex++ )
{
PGPOption *curOption = &optionList->options[optionIndex];
if( IsntNull( curOption->handlerProc ) )
{
(*curOption->handlerProc)(
optionList->context,
kPGPOptionHandler_FreeDataOperation,
curOption->type,
curOption->value, curOption->valueSize,
NULL, NULL );
}
if( IsntNull( curOption->subOptions ) )
{
pgpAssert( ( curOption->subOptions->flags &
kPGPOptionListFlag_PersistentList ) == 0 );
pgpFreeOptionListInternal( curOption->subOptions, TRUE );
}
}
pgpContextMemFree( optionList->context, optionList->options );
pgpContextMemFree( optionList->context, optionList );
}
}
}
void
pgpFreeOptionList(PGPOptionListRef optionList)
{
pgpFreeOptionListInternal( optionList, TRUE );
}
PGPOptionListRef
pgpNewOptionList(
PGPContextRef context,
PGPBoolean createPersistentList)
{
PGPOptionListRef optionList;
optionList = (PGPOptionListRef)
pgpContextMemAlloc( context, sizeof( *optionList ), 0);
if( IsntNull( optionList ) )
{
pgpClearMemory( optionList, sizeof( *optionList ) );
optionList->options = (PGPOption *)
pgpContextMemAlloc( context, sizeof( PGPOption ), 0);
if( IsntNull( optionList->options ) )
{
pgpClearMemory( optionList->options, sizeof( PGPOption ) );
optionList->magic = kPGPOptionList_Magic;
optionList->maxOptions = 1;
optionList->context = context;
optionList->version.majorVersion = kPGPOptionList_MajorVersion;
optionList->version.minorVersion = kPGPOptionList_MinorVersion;
if( createPersistentList )
optionList->flags |= kPGPOptionListFlag_PersistentList;
}
else
{
pgpContextMemFree( optionList->context, optionList );
optionList = kPGPOutOfMemoryOptionListRef;
}
}
else
{
/*
** We ran out of memory allocating the PGPOptionList (very rare
** case). Point at the preallocated option list in the context
** to handle this case.
*/
optionList = kPGPOutOfMemoryOptionListRef;
}
return( optionList );
}
/*____________________________________________________________________________
Grow an existing PGPOptionList by a specified number of PGPOption
elements. The new elements are cleared out.
____________________________________________________________________________*/
static PGPError
pgpGrowOptionList(
PGPOptionListRef optionList,
PGPUInt32 numNewOptions)
{
PGPError err;
pgpAssert( pgpOptionListIsValid( optionList ) );
pgpAssert( numNewOptions > 0 );
err = pgpGetOptionListError( optionList );
if( IsntPGPError( err ) )
{
PGPUInt32 existingListSize;
PGPUInt32 newListSize;
existingListSize = sizeof( PGPOption ) * optionList->maxOptions;
newListSize = existingListSize + ( sizeof( PGPOption ) *
numNewOptions );
err = pgpContextMemRealloc( optionList->context,
(void **)&optionList->options, newListSize, 0);
if( IsntPGPError( err ) )
{
/*
** Delete existing option list direct allocation only. Sub-option
** lists are still valid.
*/
pgpClearMemory( ((char *)optionList->options) + existingListSize,
newListSize - existingListSize );
optionList->maxOptions += numNewOptions;
}
}
return( err );
}
PGPError
pgpCopyOption(
PGPContextRef context,
const PGPOption *sourceOption,
PGPOption *destOption)
{
PGPError err = kPGPError_NoErr;
pgpAssertAddrValid( sourceOption, PGPOption );
pgpAssertAddrValid( destOption, PGPOption );
*destOption = *sourceOption;
destOption->subOptions = kInvalidPGPOptionListRef;
destOption->handlerProc = NULL;
if( IsntNull( sourceOption->handlerProc ) )
{
/* We have a handler proc, so a deep copy is possibly needed. */
err = (*sourceOption->handlerProc)(
context,
kPGPOptionHandler_CopyDataOperation,
sourceOption->type,
sourceOption->value, sourceOption->valueSize,
&destOption->value, &destOption->valueSize );
if( IsntPGPError( err ) )
{
destOption->handlerProc = sourceOption->handlerProc;
}
}
if( IsntPGPError( err ) &&
PGPOptionListRefIsValid( sourceOption->subOptions ) )
{
destOption->subOptions = pgpCopyOptionList( sourceOption->subOptions );
err = pgpGetOptionListError( destOption->subOptions );
}
return( err );
}
/*____________________________________________________________________________
Add a single PGPOption to a PGPOptionList. The option is added such that
the options in the list are kept in ascending type order. No policy is
enforced at this point about which options are duplicates.
____________________________________________________________________________*/
static PGPError
pgpAddOptionToPGPOptionList(
PGPOptionListRef optionList,
const PGPOption *newOption)
{
PGPError err;
pgpAssert( pgpOptionListIsValid( optionList ) );
pgpAssertAddrValid( newOption, PGPOption );
err = pgpGetOptionListError( optionList );
if( IsntPGPError( err ) )
{
/* Do we need to grow the list? */
if( optionList->numOptions == optionList->maxOptions )
{
err = pgpGrowOptionList( optionList,
kPGPOptionList_NumGrowElements );
}
if( IsntPGPError( err ) )
{
PGPOption addedOption;
addedOption = *newOption;
addedOption.flags &= ~(kPGPOptionFlag_Recognized |
kPGPOptionFlag_Frozen );
optionList->options[optionList->numOptions] = addedOption;
++optionList->numOptions;
}
}
pgpSetOptionListError( optionList, err );
return( err );
}
PGPOptionListRef
pgpCopyOptionList(PGPOptionListRef optionList)
{
PGPOptionListRef newOptionList;
PGPError err;
newOptionList = pgpNewOptionList( optionList->context, FALSE );
err = pgpGetOptionListError( newOptionList );
if( IsntPGPError( err ) )
{
err = pgpGetOptionListError( optionList );
if( IsntPGPError( err ) )
{
PGPUInt32 optionIndex;
for( optionIndex = 0; optionIndex < optionList->numOptions;
optionIndex++)
{
PGPOption newOption;
err = pgpCopyOption( optionList->context,
&optionList->options[optionIndex],
&newOption );
if( IsntPGPError( err ) )
{
err = pgpAddOptionToPGPOptionList( newOptionList,
&newOption );
}
if( IsPGPError( err ) )
break;
}
}
}
pgpSetOptionListError( newOptionList, err );
return( newOptionList );
}
/*____________________________________________________________________________
Merge all of the OptionList records from sourceOptionList into
destOptionList and dispose of sourceOptionList if it is not a persistent
list. Assumes both option lists are real.
____________________________________________________________________________*/
static PGPError
pgpMergeOptionLists(
PGPOptionListRef sourceOptionList,
PGPOptionListRef destOptionList)
{
PGPError err = kPGPError_NoErr;
pgpAssert( pgpOptionListIsValid( sourceOptionList ) );
pgpAssert( pgpOptionListIsReal( sourceOptionList ) );
pgpAssert( pgpOptionListIsValid( destOptionList ) );
pgpAssert( pgpOptionListIsReal( destOptionList ) );
err = pgpGetOptionListError( sourceOptionList );
if( IsntPGPError( err ) )
{
err = pgpGetOptionListError( destOptionList );
if( IsntPGPError( err ) )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -