git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@7 0109f412-320b-0410-ab79-c3e0c5ffbbe6
1579 lines
37 KiB
C++
1579 lines
37 KiB
C++
//-------------------------------------------------------------------------
|
|
// Desc: Routines to verify all dictionary syntax.
|
|
// Tabs: 3
|
|
//
|
|
// Copyright (c) 1992-2006 Novell, Inc. All Rights Reserved.
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of version 2 of the GNU General Public
|
|
// License as published by the Free Software Foundation.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, contact Novell, Inc.
|
|
//
|
|
// To contact Novell about this file by physical or electronic mail,
|
|
// you may find current contact information at www.novell.com
|
|
//
|
|
// $Id: ddprep.cpp 12329 2006-01-20 17:49:30 -0700 (Fri, 20 Jan 2006) ahodgkinson $
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include "flaimsys.h"
|
|
|
|
#define FDD_MAX_VALUE_SIZE 64
|
|
|
|
FSTATIC RCODE fdictAddDictIndex(
|
|
TDICT * pTDict);
|
|
|
|
FSTATIC RCODE DDFieldParse(
|
|
TDICT * pTDict,
|
|
DDENTRY * pDDEntry,
|
|
FlmRecord * pRecord,
|
|
FLMUINT uiDictRecNum);
|
|
|
|
FSTATIC RCODE DDGetReference(
|
|
FlmRecord * pRecord,
|
|
void * pvField,
|
|
const char * pszBuffer,
|
|
FLMUINT * puiIdRef);
|
|
|
|
FSTATIC RCODE DDAllocEntry(
|
|
TDICT * pTDict,
|
|
FlmRecord * pRecord,
|
|
FLMUINT uiDictRecNum,
|
|
DDENTRY ** ppDDEntryRV);
|
|
|
|
FSTATIC RCODE DDIxParse(
|
|
TDICT * pTDict,
|
|
DDENTRY * pDDEntry,
|
|
FlmRecord * pRecord,
|
|
void * pvField);
|
|
|
|
FSTATIC RCODE DDBuildFldPath(
|
|
TDICT * pTDict,
|
|
TIFD ** ppTIfd,
|
|
FlmRecord * pRecord,
|
|
void * pvField,
|
|
FLMUINT uiBaseNum);
|
|
|
|
FSTATIC FLMBOOL DDMoveWord(
|
|
char * pucDest,
|
|
char * pucSrc,
|
|
FLMUINT uiMaxDestLen,
|
|
FLMUINT * puiPos);
|
|
|
|
FSTATIC RCODE DDContainerParse(
|
|
TDICT * pTDict,
|
|
DDENTRY * pDDEntry,
|
|
FlmRecord * pRecord);
|
|
|
|
FSTATIC void DDTextToNative(
|
|
FlmRecord * pRecord,
|
|
void * pvField,
|
|
char * pszBuffer,
|
|
FLMUINT uiBufLen,
|
|
FLMUINT * puiBufLen);
|
|
|
|
FSTATIC RCODE DDParseStateOptions(
|
|
FlmRecord * pRecord,
|
|
void * pvField,
|
|
FLMUINT * puiFldInfo);
|
|
|
|
FSTATIC RCODE DDEncDefParse(
|
|
TDICT * pTDict,
|
|
DDENTRY * pDDEntry,
|
|
FlmRecord * pRecord,
|
|
FLMUINT uiDictRecNum);
|
|
|
|
FSTATIC RCODE DDGetEncKey(
|
|
TDICT * pTDict,
|
|
FlmRecord * pRecord,
|
|
void * pvField,
|
|
TENCDEF * pTEncDef);
|
|
|
|
#define MAX_ENC_TYPES 3
|
|
|
|
// NOTE: If you change the arrangement of the values in this array, make sure
|
|
// you search the entire codebase for references to DDEncOpts and DDGetEncType
|
|
// and verify that the changes won't cause problems. This is particularly
|
|
// important because these values DO NOT match up exactly with the values in
|
|
// the SMEncryptionScheme enum that's used at the SMI level.
|
|
|
|
char * DDEncOpts[ MAX_ENC_TYPES] =
|
|
{
|
|
"aes",
|
|
"des3",
|
|
"des"
|
|
};
|
|
|
|
#define START_DD_INDEX_OPTS 0
|
|
#define DD_IX_FIELD_OPT 0
|
|
#define DD_IX_COMPOUND_OPT 1
|
|
#define DD_IX_UPPER_OPT 2
|
|
#define DD_IX_EACHWORD_OPT 3
|
|
#define DD_IX_MIXED_OPT 4
|
|
#define DD_IX_CONTEXT_OPT 5
|
|
#define DD_IX_POST_OPT 6
|
|
#define MAX_DD_INDEX_OPTS 7
|
|
|
|
/****************************************************************************
|
|
Desc: Read all data dictionary records parsing and sending to process.
|
|
All temporary structures are off of pTDict. pTDict must be setup.
|
|
****************************************************************************/
|
|
RCODE fdictProcessAllDictRecs(
|
|
FDB * pDb,
|
|
TDICT * pTDict)
|
|
{
|
|
RCODE rc;
|
|
LFILE * pLFile = pTDict->pLFile;
|
|
BTSK stackBuf[ BH_MAX_LEVELS ]; // Stack to hold b-tree variables
|
|
BTSK * stack = stackBuf; // Points to proper stack frame
|
|
FLMBYTE btKeyBuf[ DRN_KEY_SIZ +8]; // Key buffer pointed to by stack
|
|
FLMBYTE key[4]; // Used for dummy empty key
|
|
FLMUINT uiDrn;
|
|
FlmRecord * pRecord = NULL;
|
|
|
|
// Add the dictionary index to the front of TDICT.
|
|
if( RC_BAD( rc = fdictAddDictIndex( pTDict)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Position to the first of the data dictionary data records & read.
|
|
FSInitStackCache( &stackBuf [0], BH_MAX_LEVELS);
|
|
stack->pKeyBuf = btKeyBuf;
|
|
longToByte( 0, key);
|
|
if( RC_BAD(rc = FSBtSearch( pDb, pLFile, &stack, key, DRN_KEY_SIZ, 0 )))
|
|
goto Exit;
|
|
|
|
// Special case of no records.
|
|
if( stack->uiCmpStatus == BT_END_OF_DATA)
|
|
goto Exit;
|
|
stack->uiFlags = NO_STACK; // Fake out the stack for speed.
|
|
|
|
do
|
|
{
|
|
uiDrn = (FLMUINT) byteToLong( btKeyBuf);
|
|
if( uiDrn == DRN_LAST_MARKER)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// VERY IMPORTANT NOTE:
|
|
// DO NOT READ FROM CACHE - THE RECORD MAY
|
|
// NOT HAVE BEEN PUT INTO RECORD CACHE YET, AND WE NEED TO HAVE
|
|
// THE CORRECT VERSION OF THE RECORD.
|
|
|
|
if( RC_BAD( rc = FSReadElement( pDb, &pDb->TempPool, pLFile,
|
|
uiDrn, stack, TRUE, &pRecord, NULL, NULL)))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( RC_BAD(rc = fdictProcessRec( pTDict, pRecord, uiDrn)))
|
|
{
|
|
pDb->Diag.uiDrn = uiDrn;
|
|
pDb->Diag.uiInfoFlags |= FLM_DIAG_DRN;
|
|
if( pTDict->uiBadField != 0)
|
|
{
|
|
pDb->Diag.uiFieldNum = pTDict->uiBadField;
|
|
pDb->Diag.uiInfoFlags |= FLM_DIAG_FIELD_NUM;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Position to the next record - SUCCESS or FERR_BT_END_OF_DATA
|
|
rc = FSNextRecord( pDb, pLFile, stack);
|
|
|
|
} while( RC_OK(rc));
|
|
|
|
rc = (rc == FERR_BT_END_OF_DATA) ? FERR_OK : rc;
|
|
|
|
Exit:
|
|
|
|
if( pRecord)
|
|
{
|
|
pRecord->Release();
|
|
}
|
|
|
|
FSReleaseStackCache( stackBuf, BH_MAX_LEVELS, FALSE);
|
|
return( rc );
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Add the dictionary index to pTDict.
|
|
****************************************************************************/
|
|
RCODE fdictAddDictIndex(
|
|
TDICT * pTDict)
|
|
{
|
|
RCODE rc;
|
|
DDENTRY * pDDEntry;
|
|
TIXD * pTIxd;
|
|
TIFD * pTIfd;
|
|
TIFP * pTIfp;
|
|
|
|
if( RC_BAD( rc = DDAllocEntry( pTDict, NULL, FLM_DICT_INDEX, &pDDEntry)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pDDEntry->uiType = ITT_INDEX_TYPE;
|
|
|
|
if( (pTIxd = (TIXD *) GedPoolAlloc( &pTDict->pool, sizeof( TIXD))) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
pTDict->uiNewIxds++;
|
|
pDDEntry->vpDef = (void *) pTIxd;
|
|
pTIxd->uiFlags = IXD_UNIQUE;
|
|
pTIxd->uiContainerNum = FLM_DICT_CONTAINER;
|
|
pTIxd->uiNumFlds = 1;
|
|
pTIxd->uiLanguage = pTDict->uiDefaultLanguage;
|
|
pTIxd->uiEncId = 0;
|
|
|
|
if( (pTIfd = (TIFD *) GedPoolAlloc( &pTDict->pool, sizeof( TIFD))) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
pTIxd->pNextTIfd = pTIfd;
|
|
pTDict->uiNewIfds++;
|
|
pTIfd->pTIfp = NULL;
|
|
pTIfd->pNextTIfd = NULL;
|
|
pTIfd->uiFlags = (FLMUINT)(IFD_FIELD | FLM_TEXT_TYPE);
|
|
pTIfd->uiNextFixupPos = 0;
|
|
pTIfd->uiLimit = IFD_DEFAULT_LIMIT;
|
|
pTIfd->uiCompoundPos = 0;
|
|
|
|
if( (pTIfp = (TIFP *) GedPoolAlloc( &pTDict->pool, sizeof( TIFP ))) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
pTDict->uiNewFldPaths += 2;
|
|
pTIfd->pTIfp = pTIfp;
|
|
|
|
pTIfp->pNextTIfp = NULL;
|
|
pTIfp->bFieldInThisDict = FALSE;
|
|
pTIfp->uiFldNum = FLM_NAME_TAG;
|
|
|
|
Exit:
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Process a single data dictionary record. Parse the record for syntax
|
|
errors depending on flag value. Only supports adding new stuff
|
|
to pTDict.
|
|
****************************************************************************/
|
|
RCODE fdictProcessRec(
|
|
TDICT * pTDict,
|
|
FlmRecord * pRecord,
|
|
FLMUINT uiDictRecNum)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
DDENTRY * pDDEntry;
|
|
void * pvField = pRecord->root();
|
|
|
|
// Ignore items with root nodes that are in the unregistered range.
|
|
|
|
if( pRecord->getFieldID( pvField) >= FLM_UNREGISTERED_TAGS)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Parse only on modify or add.
|
|
|
|
switch( pRecord->getFieldID( pvField))
|
|
{
|
|
case FLM_FIELD_TAG:
|
|
{
|
|
if( RC_BAD( rc = DDAllocEntry(
|
|
pTDict, pRecord, uiDictRecNum, &pDDEntry)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pDDEntry->uiType = 0; // Type of zero means field.
|
|
if( RC_BAD( rc = DDFieldParse( pTDict, pDDEntry,
|
|
pRecord, uiDictRecNum)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FLM_INDEX_TAG:
|
|
{
|
|
if( RC_BAD( rc = DDAllocEntry(
|
|
pTDict, pRecord, uiDictRecNum, &pDDEntry)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pDDEntry->uiType = ITT_INDEX_TYPE;
|
|
if( RC_BAD( rc = DDIxParse( pTDict, pDDEntry, pRecord, pvField)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pTDict->uiNewIxds++;
|
|
break;
|
|
}
|
|
|
|
case FLM_CONTAINER_TAG:
|
|
{
|
|
if( RC_BAD( rc = DDAllocEntry(
|
|
pTDict, pRecord, uiDictRecNum, &pDDEntry)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pDDEntry->uiType = ITT_CONTAINER_TYPE;
|
|
if( RC_BAD( rc = DDContainerParse( pTDict, pDDEntry, pRecord)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pTDict->uiTotalLFiles++;
|
|
break;
|
|
}
|
|
case FLM_ENCDEF_TAG:
|
|
{
|
|
if( RC_BAD( rc = DDAllocEntry(
|
|
pTDict, pRecord, uiDictRecNum, &pDDEntry)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pDDEntry->uiType = ITT_ENCDEF_TYPE;
|
|
if (RC_BAD( rc = DDEncDefParse( pTDict, pDDEntry, pRecord, uiDictRecNum)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
case FLM_AREA_TAG:
|
|
case FLM_RESERVED_TAG:
|
|
{
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
// Cannot allow anything else to pass through the dictionary.
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Allocate, check and add a name to the DDEntry structure.
|
|
****************************************************************************/
|
|
FSTATIC RCODE DDAllocEntry(
|
|
TDICT * pTDict,
|
|
FlmRecord * pRecord,
|
|
FLMUINT uiDictRecNum,
|
|
DDENTRY ** ppDDEntryRV)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
DDENTRY * pNewEntry;
|
|
|
|
pNewEntry = (DDENTRY *)GedPoolAlloc( &pTDict->pool, sizeof(DDENTRY));
|
|
if( !pNewEntry)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
pNewEntry->pNextEntry = NULL;
|
|
pNewEntry->vpDef = NULL;
|
|
pNewEntry->uiEntryNum = uiDictRecNum;
|
|
pNewEntry->uiType = 0;
|
|
|
|
// Zero length name NOT allowed for dictionary items.
|
|
|
|
if( pRecord)
|
|
{
|
|
if( pRecord->getDataLength( pRecord->root()) == 0)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if( pTDict->pLastEntry)
|
|
{
|
|
pTDict->pLastEntry->pNextEntry = pNewEntry;
|
|
}
|
|
else
|
|
{
|
|
pTDict->pFirstEntry = pNewEntry;
|
|
}
|
|
pTDict->pLastEntry = pNewEntry;
|
|
*ppDDEntryRV = pNewEntry;
|
|
|
|
Exit:
|
|
|
|
return( rc );
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Parse field definition
|
|
****************************************************************************/
|
|
FSTATIC RCODE DDFieldParse(
|
|
TDICT * pTDict,
|
|
DDENTRY * pDDEntry,
|
|
FlmRecord * pRecord,
|
|
FLMUINT uiDictRecNum)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
TFIELD * pTField;
|
|
void * pvField;
|
|
|
|
if( (pTField = (TFIELD *)GedPoolAlloc( &pTDict->pool, sizeof(TFIELD))) == NULL)
|
|
{
|
|
return( RC_SET( FERR_MEM));
|
|
}
|
|
|
|
pTField->uiFldNum = uiDictRecNum;
|
|
pTField->uiFldInfo = FLM_CONTEXT_TYPE;
|
|
pDDEntry->vpDef = (void *) pTField;
|
|
|
|
if( (pvField = pRecord->firstChild( pRecord->root())) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
|
|
for( ; pvField; pvField = pRecord->nextSibling( pvField))
|
|
{
|
|
switch( pRecord->getFieldID( pvField))
|
|
{
|
|
case FLM_TYPE_TAG:
|
|
{
|
|
rc = DDGetFieldType( pRecord, pvField, &pTField->uiFldInfo);
|
|
break;
|
|
}
|
|
|
|
case FLM_STATE_TAG:
|
|
{
|
|
rc = DDParseStateOptions( pRecord, pvField, &pTField->uiFldInfo);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
if( pRecord->getFieldID( pvField) < FLM_UNREGISTERED_TAGS &&
|
|
pRecord->getFieldID( pvField) != FLM_COMMENT_TAG)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
if( RC_BAD(rc) && pvField)
|
|
{
|
|
pTDict->uiBadField = pRecord->getFieldID( pvField);
|
|
}
|
|
return( rc );
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Returns the fields data type. May be called outside of DDPREP.C
|
|
****************************************************************************/
|
|
RCODE DDGetFieldType(
|
|
FlmRecord * pRecord,
|
|
void * pvField,
|
|
FLMUINT * puiFldInfo)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
char szNativeBuf[ FDD_MAX_VALUE_SIZE];
|
|
|
|
DDTextToNative( pRecord, pvField, szNativeBuf, FDD_MAX_VALUE_SIZE, NULL );
|
|
|
|
// Parse the type keyword - only one type allowed.
|
|
|
|
if (f_strnicmp( szNativeBuf, "text", 4) == 0)
|
|
{
|
|
*puiFldInfo = FLM_TEXT_TYPE;
|
|
}
|
|
else if (f_strnicmp( szNativeBuf, "numb", 4) == 0)
|
|
{
|
|
*puiFldInfo = FLM_NUMBER_TYPE;
|
|
}
|
|
else if (f_strnicmp( szNativeBuf, "bina", 4) == 0)
|
|
{
|
|
*puiFldInfo = FLM_BINARY_TYPE;
|
|
}
|
|
else if (f_strnicmp( szNativeBuf, "cont", 4) == 0)
|
|
{
|
|
*puiFldInfo = FLM_CONTEXT_TYPE;
|
|
}
|
|
else if (f_strnicmp( szNativeBuf, "blob", 4) == 0)
|
|
{
|
|
*puiFldInfo = FLM_BLOB_TYPE;
|
|
}
|
|
else
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Parses the 'state' option that is found within the 'field'
|
|
dictionary definition.
|
|
Format: state [checking | unused | purge | active]
|
|
****************************************************************************/
|
|
FSTATIC RCODE DDParseStateOptions(
|
|
FlmRecord * pRecord,
|
|
void * pvField,
|
|
FLMUINT * puiFldInfo)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
char szNativeBuf[ FDD_MAX_VALUE_SIZE];
|
|
|
|
DDTextToNative( pRecord, pvField, szNativeBuf, FDD_MAX_VALUE_SIZE, NULL);
|
|
|
|
// Parse the 'state' keyword - only one type allowed
|
|
|
|
if( f_strnicmp( szNativeBuf, "chec", 4) == 0)
|
|
{
|
|
// 0xFFCF is used to clear out any existing field 'state' value
|
|
|
|
*puiFldInfo = (FLMUINT)((*puiFldInfo & ~ITT_FLD_STATE_MASK) | ITT_FLD_STATE_CHECKING);
|
|
}
|
|
else if( f_strnicmp( szNativeBuf, "unus", 4) == 0)
|
|
{
|
|
*puiFldInfo = (FLMUINT)((*puiFldInfo & ~ITT_FLD_STATE_MASK) | ITT_FLD_STATE_UNUSED);
|
|
}
|
|
else if( f_strnicmp( szNativeBuf, "purg", 4) == 0)
|
|
{
|
|
*puiFldInfo = (FLMUINT)((*puiFldInfo & ~ITT_FLD_STATE_MASK) | ITT_FLD_STATE_PURGE);
|
|
}
|
|
else if( f_strnicmp( szNativeBuf, "acti", 4) == 0)
|
|
{
|
|
*puiFldInfo = (FLMUINT)((*puiFldInfo & ~ITT_FLD_STATE_MASK) | ITT_FLD_STATE_ACTIVE);
|
|
}
|
|
else
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
}
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Get a number reference and set in the (OUT) parameter.
|
|
****************************************************************************/
|
|
FSTATIC RCODE DDGetReference(
|
|
FlmRecord * pRecord,
|
|
void * pvField,
|
|
const char * pszBuffer,
|
|
FLMUINT * puiIdRef)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
*puiIdRef = 0;
|
|
if( pszBuffer)
|
|
{
|
|
if( !(*pszBuffer))
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
|
|
*puiIdRef = f_atoud( pszBuffer);
|
|
}
|
|
else
|
|
{
|
|
if( RC_BAD( rc = pRecord->getUINT( pvField, puiIdRef)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
Desc: Returns the encryption type. May be called outside of DDPREP.C
|
|
****************************************************************************/
|
|
RCODE DDGetEncType(
|
|
FlmRecord * pRecord,
|
|
void * pvField,
|
|
FLMUINT * puiFldInfo)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
FLMUINT uiType;
|
|
char szNativeBuf[ FDD_MAX_VALUE_SIZE];
|
|
|
|
DDTextToNative( pRecord, pvField, szNativeBuf, FDD_MAX_VALUE_SIZE, NULL );
|
|
|
|
// Parse the type keyword - only one type allowed.
|
|
|
|
for( uiType = 0;
|
|
uiType < MAX_ENC_TYPES ;
|
|
uiType++)
|
|
{
|
|
if( f_strnicmp( szNativeBuf, DDEncOpts[ uiType],
|
|
f_strlen(DDEncOpts[ uiType])) == 0)
|
|
{
|
|
*puiFldInfo = uiType;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
|
|
Exit:
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Returns the binary key info. May be called outside of DDPREP.C
|
|
****************************************************************************/
|
|
FSTATIC RCODE DDGetEncKey(
|
|
TDICT * pTDict,
|
|
FlmRecord * pRecord,
|
|
void * pvField,
|
|
TENCDEF * pTEncDef)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
char * pucBuffer = NULL;
|
|
FLMUINT uiLength;
|
|
|
|
pTEncDef->uiLength = 0;
|
|
|
|
if (RC_BAD( rc = pRecord->getNativeLength( pvField, &uiLength)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiLength++;
|
|
|
|
// Allocate the buffer from the pool so it will be easily freed later.
|
|
|
|
if( (pucBuffer = (char *)GedPoolAlloc( &pTDict->pool, uiLength)) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pRecord->getNative( pvField, pucBuffer, &uiLength)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pTEncDef->uiLength = uiLength;
|
|
pTEncDef->pucKeyInfo = (FLMBYTE *)pucBuffer;
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Parse an data dictionary index definition for correct syntax &
|
|
assign the correct attributes. Build the pcode buffer for the index.
|
|
Return: RCODE - SUCCESS or FERR_SYNTAX
|
|
Format:
|
|
|
|
0 index <psName> # FLM_INDEX_TAG
|
|
[ 1 area [ 0 | <ID>]] # FLM_AREA_TAG - QF files area, 0 = "same as DB"
|
|
[ 1 container {DEFAULT | <ID>}] # FLM_CONTAINER_TAG - indexes span only one container
|
|
[ 1 count [ KEYS &| REFS]] # FLM_COUNT_TAG - key count of keys and/or refs
|
|
[ 1 language {US | <language>}] # FLM_LANGUAGE_TAG - for full-text parsing and/or sorting
|
|
[ 1 positioning] # FLM_POSITIONING_TAG - full reference counts at all b-tree elements
|
|
[ 1 encdef <EncryptionDefId>] # FLM_ENCDEF_TAG - identify the encryption definition to use
|
|
|
|
1 key [EACHWORD] # FLM_KEY_TAG - 'use' defaults based on type
|
|
[ 2 base <ID>] # FLM_BASE_TAG - base rec/field for fields below
|
|
[ 2 combinations <below> # FLM_COMBINATIONS_TAG - how to handle repeating fields
|
|
{ ALL | NORMALIZED}]
|
|
[ 2 post] # FLM_POST_TAG - case-flags post-pended to key
|
|
[ 2 required*] # FLM_REQUIRED_TAG - key value is required
|
|
[ 2 unique] # FLM_UNIQUE_TAG - key has only 1 reference
|
|
{ 2 <field> }... # FLM_FIELD_TAG - compound key if 2 or more
|
|
[ 3 case mixed | upper] # FLM_CASE_TAG - text-only, define chars case
|
|
[ 3 <field>]... # FLM_FIELD_TAG - alternate field(s)
|
|
[ 3 paired] # FLM_PAIRED_TAG - add field ID to key
|
|
[ 3 optional* # FLM_OPTIONAL_TAG - component's value is optional
|
|
| 3 required] # FLM_REQUIRED_TAG - component's value is required
|
|
[ 3 use eachword|value|field|minspaces|nounderscore|nospace|nodash] # FLM_USE_TAG
|
|
|
|
<field> ==
|
|
n field <field path> # path identifies field -- maybe "based"
|
|
[ m type <data type>] # FLM_TYPE_TAG - only for ixing unregistered fields
|
|
|
|
Please Note: This code only supports the minimal old 11 index format
|
|
needed for skads databases.
|
|
****************************************************************************/
|
|
FSTATIC RCODE DDIxParse(
|
|
TDICT * pTDict,
|
|
DDENTRY * pDDEntry, // Points to defined entry.
|
|
FlmRecord * pRecord, // Index definition record.
|
|
void * pvField)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
FLMUINT uiIfdFlags;
|
|
FLMUINT uiTempIfdFlags;
|
|
FLMUINT uiBaseNum;
|
|
FLMUINT uiNLen;
|
|
TIXD * pTIxd;
|
|
TIFD * pLastTIfd;
|
|
TIFD * pTIfd;
|
|
void * pvTempField = NULL;
|
|
void * pvIfdField = NULL;
|
|
char szNativeBuf[ 64];
|
|
FLMUINT uiCompoundPos;
|
|
FLMUINT uiTemp;
|
|
FLMBOOL bHasRequiredTag = TRUE;
|
|
FLMBOOL bOld11Mode = FALSE;
|
|
|
|
if( (pTIxd = (TIXD *) GedPoolAlloc( &pTDict->pool, sizeof( TIXD))) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
pTIxd->pNextTIfd = NULL;
|
|
pTIxd->uiFlags = 0;
|
|
pTIxd->uiContainerNum = FLM_DATA_CONTAINER;
|
|
pTIxd->uiNumFlds = 0;
|
|
pTIxd->uiLanguage = pTDict->uiDefaultLanguage;
|
|
pTIxd->uiEncId = 0;
|
|
|
|
if( (pvField = pRecord->firstChild( pRecord->root())) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
|
|
pLastTIfd = NULL;
|
|
for( ; pvField; pvField = pRecord->nextSibling( pvField))
|
|
{
|
|
switch ( pRecord->getFieldID( pvField))
|
|
{
|
|
case FLM_CONTAINER_TAG:
|
|
{
|
|
char szTmpBuf [50];
|
|
FLMUINT uiLen = sizeof( szTmpBuf);
|
|
|
|
// See if a special keyword is used - ALL or *
|
|
|
|
if ((pRecord->getDataType( pvField) == FLM_TEXT_TYPE) &&
|
|
(RC_OK( pRecord->getNative( pvField, szTmpBuf, &uiLen))) &&
|
|
(f_stricmp( "ALL", szTmpBuf) == 0 ||
|
|
f_stricmp( "*", szTmpBuf) == 0))
|
|
{
|
|
if (pTDict->pDb->pFile->FileHdr.uiVersionNum < FLM_VER_4_50)
|
|
{
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
}
|
|
|
|
// Zero will mean all containers
|
|
|
|
pTIxd->uiContainerNum = 0;
|
|
}
|
|
else
|
|
{
|
|
if( RC_BAD( rc = DDGetReference( pRecord, pvField, NULL,
|
|
&pTIxd->uiContainerNum)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if( pTIxd->uiContainerNum == 0)
|
|
{
|
|
pTIxd->uiContainerNum = FLM_DATA_CONTAINER;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FLM_COUNT_TAG:
|
|
pTIxd->uiFlags |= IXD_COUNT;
|
|
break;
|
|
|
|
case FLM_LANGUAGE_TAG:
|
|
uiNLen = sizeof( szNativeBuf);
|
|
(void) pRecord->getNative( pvField, szNativeBuf, &uiNLen);
|
|
pTIxd->uiLanguage = FlmLanguage( szNativeBuf);
|
|
break;
|
|
|
|
|
|
case FLM_ENCDEF_TAG:
|
|
{
|
|
uiNLen = sizeof( szNativeBuf);
|
|
(void) pRecord->getNative( pvField, szNativeBuf, &uiNLen);
|
|
pTIxd->uiEncId = f_atoud( szNativeBuf);
|
|
flmAssert( pTIxd->uiEncId);
|
|
break;
|
|
}
|
|
|
|
case FLM_TYPE_TAG:
|
|
// Is only compound for NDS definitions. This parsers default.
|
|
bOld11Mode = TRUE;
|
|
break;
|
|
|
|
case FLM_POSITIONING_TAG:
|
|
if (pTDict->pDb->pFile->FileHdr.uiVersionNum >= FLM_VER_4_3)
|
|
{
|
|
pTIxd->uiFlags |= IXD_POSITIONING;
|
|
}
|
|
else
|
|
{
|
|
|
|
// Positioning indexes not allowed prior to 4.3
|
|
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
break;
|
|
|
|
case FLM_FIELD_TAG:
|
|
uiCompoundPos = 0;
|
|
uiBaseNum = 0;
|
|
uiIfdFlags = IFD_FIELD;
|
|
bHasRequiredTag = TRUE;
|
|
pvTempField = pvField;
|
|
bOld11Mode = TRUE;
|
|
goto Parse_Fields;
|
|
|
|
case FLM_KEY_TAG:
|
|
uiCompoundPos = 0;
|
|
uiBaseNum = 0;
|
|
uiIfdFlags = IFD_FIELD | IFD_OPTIONAL;
|
|
bHasRequiredTag = FALSE;
|
|
|
|
uiNLen = sizeof( szNativeBuf);
|
|
(void) pRecord->getNative( pvField, szNativeBuf, &uiNLen);
|
|
|
|
if( f_strnicmp( szNativeBuf, "EACH", 4) == 0)
|
|
{
|
|
pTIxd->uiFlags |= IXD_EACHWORD;
|
|
uiIfdFlags = IFD_EACHWORD | IFD_OPTIONAL;
|
|
}
|
|
|
|
if( (pvTempField = pRecord->firstChild( pvField)) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
Parse_Fields:
|
|
for( ; pvTempField; pvTempField = pRecord->nextSibling( pvTempField))
|
|
{
|
|
switch( pRecord->getFieldID( pvTempField))
|
|
{
|
|
case FLM_BASE_TAG:
|
|
if( RC_BAD( rc = DDGetReference( pRecord,
|
|
pvTempField, NULL, &uiBaseNum)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
|
|
case FLM_COMBINATIONS_TAG:
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
|
|
case FLM_POST_TAG:
|
|
pTIxd->uiFlags |= IXD_HAS_POST;
|
|
uiIfdFlags |= IFD_POST;
|
|
break;
|
|
|
|
case FLM_REQUIRED_TAG: // Default - doesn't mean anything
|
|
break;
|
|
|
|
case FLM_OPTIONAL_TAG:
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
|
|
case FLM_UNIQUE_TAG :
|
|
pTIxd->uiFlags |= IXD_UNIQUE;
|
|
uiIfdFlags |= IFD_UNIQUE_PIECE; // Set the Unique Index Flag
|
|
break;
|
|
|
|
case FLM_FIELD_TAG:
|
|
pTIxd->uiNumFlds++;
|
|
|
|
if( bOld11Mode)
|
|
{
|
|
pvField = pvTempField;
|
|
}
|
|
|
|
// Need to set IFD_COMPOUND if there is more than one field.
|
|
|
|
if( pTIxd->uiNumFlds == 1 &&
|
|
(pRecord->find( pvTempField, FLM_FIELD_TAG, 2) != NULL))
|
|
{
|
|
uiIfdFlags |= IFD_COMPOUND;
|
|
}
|
|
|
|
pTIfd = pLastTIfd;
|
|
if( RC_BAD(rc = DDBuildFldPath( pTDict, &pLastTIfd,
|
|
pRecord, pvTempField, uiBaseNum)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pLastTIfd->uiCompoundPos = uiCompoundPos++;
|
|
|
|
if( !pTIfd) // First time?
|
|
{
|
|
pTIxd->pNextTIfd = pLastTIfd; // Link first IFD
|
|
}
|
|
else
|
|
{
|
|
pTIfd->pNextTIfd = pLastTIfd;
|
|
}
|
|
uiTempIfdFlags = uiIfdFlags;
|
|
if( bOld11Mode)
|
|
{
|
|
// Default is required for each field.
|
|
uiTempIfdFlags &= ~IFD_OPTIONAL;
|
|
uiTempIfdFlags |= (IFD_REQUIRED_PIECE | IFD_REQUIRED_IN_SET);
|
|
}
|
|
|
|
for( pvIfdField = pRecord->firstChild( pvTempField);
|
|
pvIfdField; pvIfdField = pRecord->nextSibling( pvIfdField))
|
|
{
|
|
switch ( pRecord->getFieldID( pvIfdField))
|
|
{
|
|
//
|
|
// General IFD options only for this field GROUP
|
|
//
|
|
case FLM_CASE_TAG:
|
|
uiNLen = sizeof( szNativeBuf);
|
|
(void) pRecord->getNative( pvIfdField, szNativeBuf, &uiNLen);
|
|
|
|
if( f_strnicmp( szNativeBuf, "UPPE", 4) == 0)
|
|
{
|
|
uiTempIfdFlags |= IFD_UPPER;
|
|
}
|
|
break;
|
|
|
|
case FLM_FIELD_TAG:
|
|
break;
|
|
|
|
case FLM_OPTIONAL_TAG:
|
|
if( bOld11Mode)
|
|
{
|
|
// Old 11 format - default for each field is required.
|
|
uiTempIfdFlags |= IFD_OPTIONAL;
|
|
uiTempIfdFlags &= ~(IFD_REQUIRED_PIECE | IFD_REQUIRED_IN_SET);
|
|
}
|
|
// New format default is optional
|
|
break;
|
|
|
|
case FLM_PAIRED_TAG:
|
|
uiTempIfdFlags |= IFD_FIELDID_PAIR;
|
|
break;
|
|
|
|
case FLM_POST_TAG:
|
|
// FUTURE: Post piece where other pieces are not
|
|
uiTempIfdFlags |= IFD_POST;
|
|
break;
|
|
|
|
case FLM_REQUIRED_TAG:
|
|
bHasRequiredTag = TRUE;
|
|
uiTempIfdFlags &= ~IFD_OPTIONAL;
|
|
uiTempIfdFlags |= (IFD_REQUIRED_PIECE | IFD_REQUIRED_IN_SET);
|
|
break;
|
|
|
|
case FLM_LIMIT_TAG:
|
|
if( RC_BAD( pRecord->getUINT( pvIfdField, &uiTemp)) ||
|
|
uiTemp > IFD_DEFAULT_LIMIT)
|
|
{
|
|
pLastTIfd->uiLimit = IFD_DEFAULT_LIMIT;
|
|
}
|
|
else
|
|
{
|
|
pLastTIfd->uiLimit = uiTemp;
|
|
}
|
|
break;
|
|
|
|
case FLM_UNIQUE_TAG:
|
|
// FUTURE: option to select specific unique fields.
|
|
uiTempIfdFlags |= IFD_UNIQUE_PIECE;
|
|
pTIxd->uiFlags |= IXD_UNIQUE;
|
|
break;
|
|
|
|
case FLM_USE_TAG:
|
|
// All these are exclusive values. Take the last value.
|
|
uiNLen = sizeof( szNativeBuf);
|
|
(void) pRecord->getNative( pvIfdField, szNativeBuf, &uiNLen);
|
|
|
|
if( f_strnicmp( szNativeBuf, "EACH", 4) == 0)
|
|
{
|
|
uiTempIfdFlags |= IFD_EACHWORD;
|
|
uiTempIfdFlags &= ~(IFD_VALUE|IFD_SUBSTRING);
|
|
}
|
|
else if( f_strnicmp( szNativeBuf, "SUBS", 4) == 0)
|
|
{
|
|
pTIxd->uiFlags |= IXD_HAS_SUBSTRING;
|
|
uiTempIfdFlags |= IFD_SUBSTRING;
|
|
uiTempIfdFlags &= ~(IFD_VALUE|IFD_EACHWORD);
|
|
if( pLastTIfd->uiLimit == IFD_DEFAULT_LIMIT)
|
|
{
|
|
pLastTIfd->uiLimit = IFD_DEFAULT_SUBSTRING_LIMIT;
|
|
}
|
|
}
|
|
else if( f_strnicmp( szNativeBuf, "VALU", 4) == 0)
|
|
{
|
|
uiTempIfdFlags |= IFD_VALUE;
|
|
uiTempIfdFlags &= ~(IFD_EACHWORD|IFD_SUBSTRING);
|
|
}
|
|
else if( f_strnicmp( szNativeBuf, "FIEL", 4) == 0)
|
|
{
|
|
uiTempIfdFlags |= IFD_CONTEXT;
|
|
uiTempIfdFlags &= ~(IFD_VALUE|IFD_EACHWORD|IFD_SUBSTRING);
|
|
}
|
|
break;
|
|
|
|
case FLM_FILTER_TAG:
|
|
uiNLen = sizeof( szNativeBuf);
|
|
(void) pRecord->getNative( pvIfdField, szNativeBuf, &uiNLen);
|
|
|
|
if( f_strnicmp( szNativeBuf, "MINS", 4) == 0)
|
|
{
|
|
uiTempIfdFlags |= IFD_MIN_SPACES;
|
|
}
|
|
else if( f_strnicmp( szNativeBuf, "NOUN", 4) == 0)
|
|
{
|
|
uiTempIfdFlags |= IFD_NO_UNDERSCORE;
|
|
}
|
|
else if( f_strnicmp( szNativeBuf, "NOSP", 4) == 0)
|
|
{
|
|
uiTempIfdFlags |= IFD_NO_SPACE;
|
|
}
|
|
else if( f_strnicmp( szNativeBuf, "NODA", 4) == 0)
|
|
{
|
|
uiTempIfdFlags |= IFD_NO_DASH;
|
|
}
|
|
else
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if( pRecord->getFieldID( pvIfdField) < FLM_UNREGISTERED_TAGS &&
|
|
pRecord->getFieldID( pvIfdField) != FLM_COMMENT_TAG)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
break;
|
|
} // end switch
|
|
} // end for loop parsing all level 3 tags
|
|
|
|
// Parse again the level 3 field definitions. Now we
|
|
// have the IFD uiFlags value to assign each piece that
|
|
// will have the same compound position.
|
|
|
|
pLastTIfd->uiFlags |= uiTempIfdFlags;
|
|
|
|
for( pvIfdField = pRecord->firstChild( pvTempField);
|
|
pvIfdField; pvIfdField = pRecord->nextSibling( pvIfdField))
|
|
{
|
|
if( pRecord->getFieldID( pvIfdField) == FLM_FIELD_TAG )
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
}
|
|
break; // Done parsing "2 field xx yy zz"
|
|
|
|
default:
|
|
if( bOld11Mode)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( pRecord->getFieldID( pvTempField) < FLM_UNREGISTERED_TAGS &&
|
|
pRecord->getFieldID( pvTempField) != FLM_COMMENT_TAG)
|
|
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
break;
|
|
} // end switch
|
|
|
|
} // end for loop
|
|
|
|
// Special case for optional
|
|
if( !bHasRequiredTag)
|
|
{
|
|
// Set all of the IFD flags to IFD_REQUIRED_IN_SET
|
|
for( pTIfd = pTIxd->pNextTIfd; pTIfd; pTIfd = pTIfd->pNextTIfd)
|
|
{
|
|
pTIfd->uiFlags |= IFD_REQUIRED_IN_SET;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if( pRecord->getFieldID( pvField) < FLM_UNREGISTERED_TAGS &&
|
|
pRecord->getFieldID( pvField) != FLM_COMMENT_TAG)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
pDDEntry->vpDef = (void *) pTIxd;
|
|
|
|
Exit:
|
|
|
|
if( RC_BAD(rc))
|
|
{
|
|
if( pvIfdField)
|
|
pTDict->uiBadField = pRecord->getFieldID( pvIfdField);
|
|
else if( pvTempField)
|
|
pTDict->uiBadField = pRecord->getFieldID( pvTempField);
|
|
else if( pvField)
|
|
pTDict->uiBadField = pRecord->getFieldID( pvField);
|
|
}
|
|
else
|
|
{
|
|
pTDict->uiNewIxds++;
|
|
pTDict->uiNewIfds += pTIxd->uiNumFlds;
|
|
pTDict->uiNewLFiles++;
|
|
}
|
|
return( rc );
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Build field path for each index field. This function will also
|
|
check for the existence of the 'batch' option for QF indexes.
|
|
****************************************************************************/
|
|
FSTATIC RCODE DDBuildFldPath(
|
|
TDICT * pTDict,
|
|
TIFD ** ppTIfd,
|
|
FlmRecord * pRecord,
|
|
void * pvField,
|
|
FLMUINT uiBaseNum)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
TIFD * pTIfd;
|
|
TIFP * pLastFldPath;
|
|
TIFP * pTIfp;
|
|
FLMUINT uiNumInFldPath;
|
|
char szNameBuf[ 32 ];
|
|
char * pszCurrent;
|
|
char szNativeBuf[ FDD_MAX_VALUE_SIZE];
|
|
FLMUINT uiBufLen;
|
|
FLMUINT uiPos;
|
|
|
|
pTDict->uiTotalIfds++;
|
|
if( (pTIfd = (TIFD *) GedPoolAlloc( &pTDict->pool, sizeof( TIFD))) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
pTIfd->pTIfp = NULL;
|
|
pTIfd->pNextTIfd = NULL;
|
|
pTIfd->uiFlags = 0;
|
|
pTIfd->uiNextFixupPos = 0;
|
|
pTIfd->uiLimit = IFD_DEFAULT_LIMIT;
|
|
pTIfd->uiCompoundPos = 0;
|
|
|
|
pLastFldPath = NULL;
|
|
*ppTIfd = pTIfd;
|
|
|
|
// Build the field paths
|
|
|
|
DDTextToNative( pRecord, pvField, szNativeBuf,
|
|
FDD_MAX_VALUE_SIZE, &uiBufLen);
|
|
|
|
pszCurrent = szNativeBuf;
|
|
uiNumInFldPath = uiPos = 0;
|
|
|
|
if( uiBaseNum )
|
|
{
|
|
uiNumInFldPath++;
|
|
if( (pTIfp = (TIFP *) GedPoolAlloc( &pTDict->pool,
|
|
sizeof( TIFP ))) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
pTIfp->pNextTIfp = NULL;
|
|
pTIfp->bFieldInThisDict = FALSE;
|
|
pTIfp->uiFldNum = uiBaseNum;
|
|
pTIfd->pTIfp = pTIfp;
|
|
pLastFldPath = pTIfp;
|
|
}
|
|
|
|
while( uiPos < uiBufLen)
|
|
{
|
|
uiNumInFldPath++;
|
|
if( DDMoveWord( szNameBuf, pszCurrent,
|
|
sizeof( szNameBuf ), &uiPos ) == FALSE )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( (pTIfp = (TIFP *) GedPoolAlloc( &pTDict->pool,
|
|
sizeof( TIFP ))) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
pTIfp->pNextTIfp = NULL;
|
|
pTIfp->bFieldInThisDict = FALSE;
|
|
|
|
if( pTIfd->pTIfp == NULL)
|
|
{
|
|
pTIfd->pTIfp = pTIfp;
|
|
}
|
|
else
|
|
{
|
|
pLastFldPath->pNextTIfp = pTIfp;
|
|
}
|
|
|
|
pLastFldPath = pTIfp;
|
|
|
|
// See if there is a wildcard in the path.
|
|
|
|
if (f_stricmp( szNameBuf, "*") == 0)
|
|
{
|
|
if (pTDict->pDb->pFile->FileHdr.uiVersionNum < FLM_VER_4_50)
|
|
{
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
}
|
|
else
|
|
{
|
|
pTIfp->uiFldNum = FLM_ANY_FIELD;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( RC_BAD( rc = DDGetReference( NULL, NULL, szNameBuf,
|
|
&pTIfp->uiFldNum)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( uiNumInFldPath == 0)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
|
|
// Cannot have wildcard in last field of field path.
|
|
|
|
if (pLastFldPath->uiFldNum == FLM_ANY_FIELD)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
|
|
// Single field has the field NULL terminated
|
|
|
|
if( uiNumInFldPath == 1 )
|
|
{
|
|
pTDict->uiNewFldPaths += 2;
|
|
}
|
|
else
|
|
{
|
|
// The field paths are stored child to parent and parent to child
|
|
// each are zero terminated.
|
|
|
|
pTDict->uiNewFldPaths += 2 * (uiNumInFldPath + 1);
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Parse a data dictionary domain definition for correct syntax &
|
|
assign the correct attributes.
|
|
****************************************************************************/
|
|
FSTATIC RCODE DDContainerParse(
|
|
TDICT * pTDict,
|
|
DDENTRY * pDDEntry,
|
|
FlmRecord * pRecord)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvField = NULL;
|
|
|
|
if( pDDEntry)
|
|
{
|
|
|
|
if( (pvField = pRecord->firstChild( pRecord->root())) != NULL)
|
|
{
|
|
for( ; pvField; pvField = pRecord->nextSibling( pvField))
|
|
{
|
|
// Only option is unregistered fields
|
|
|
|
if( pRecord->getFieldID( pvField) < FLM_FREE_TAG_NUMS)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
if( RC_BAD(rc) && pvField)
|
|
{
|
|
pTDict->uiBadField = pRecord->getFieldID( pvField);
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Parse a data dictionary domain definition for correct syntax &
|
|
assign the correct attributes.
|
|
****************************************************************************/
|
|
FSTATIC RCODE DDEncDefParse(
|
|
TDICT * pTDict,
|
|
DDENTRY * pDDEntry,
|
|
FlmRecord * pRecord,
|
|
FLMUINT uiDictRecNum)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvField = NULL;
|
|
TENCDEF * pTEncDef;
|
|
|
|
// Make sure the version of the database is correct for encryption.
|
|
|
|
if (pTDict->pDb->pFile->FileHdr.uiVersionNum < FLM_VER_4_60)
|
|
{
|
|
rc = RC_SET( FERR_UNSUPPORTED_FEATURE);
|
|
goto Exit;
|
|
}
|
|
|
|
if( (pTEncDef = (TENCDEF *)GedPoolAlloc( &pTDict->pool,
|
|
sizeof(TENCDEF))) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
pTEncDef->uiRecNum = uiDictRecNum;
|
|
pTEncDef->uiAlgType = 0;
|
|
pTEncDef->uiState = 0;
|
|
pTEncDef->pucKeyInfo = NULL;
|
|
pTEncDef->uiLength = 0;
|
|
|
|
if( pDDEntry)
|
|
{
|
|
|
|
if( (pvField = pRecord->firstChild( pRecord->root())) != NULL)
|
|
{
|
|
for( ; pvField; pvField = pRecord->nextSibling( pvField))
|
|
{
|
|
switch ( pRecord->getFieldID( pvField) )
|
|
{
|
|
case FLM_TYPE_TAG:
|
|
{
|
|
// Get the encryption type.
|
|
if (RC_BAD( rc = DDGetEncType( pRecord,
|
|
pvField,
|
|
&pTEncDef->uiAlgType)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FLM_KEY_TAG:
|
|
{
|
|
// Get the key information.
|
|
if (RC_BAD( rc = DDGetEncKey( pTDict,
|
|
pRecord,
|
|
pvField,
|
|
pTEncDef)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FLM_STATE_TAG:
|
|
{
|
|
// Get the status information.
|
|
if (RC_BAD( rc = DDParseStateOptions( pRecord,
|
|
pvField,
|
|
&pTEncDef->uiState)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
pDDEntry->vpDef = (void *)pTEncDef;
|
|
|
|
}
|
|
else
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (RC_BAD( rc) && pvField)
|
|
{
|
|
pTDict->uiBadField = pRecord->getFieldID( pvField);
|
|
}
|
|
|
|
return( rc );
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Move word delimited by spaces from src to dest. Used to move a
|
|
word at a time for field path lists.
|
|
Notes: Isolated so changes can be made to delemeting NAMES.
|
|
Visit: Still bugs when name > buffer size - won't happen because only #'s
|
|
****************************************************************************/
|
|
FSTATIC FLMBOOL DDMoveWord(
|
|
char * pucDest,
|
|
char * pucSrc,
|
|
FLMUINT uiMaxDestLen,
|
|
FLMUINT * puiPos)
|
|
{
|
|
FLMBOOL bFoundWord = TRUE;
|
|
FLMUINT uiPos = *puiPos;
|
|
char * pMatch;
|
|
FLMUINT uiBytesToCopy;
|
|
|
|
pucSrc += uiPos;
|
|
while( *pucSrc == NATIVE_SPACE)
|
|
{
|
|
pucSrc++;
|
|
}
|
|
|
|
pMatch = pucSrc;
|
|
while( *pMatch > NATIVE_SPACE)
|
|
{
|
|
pMatch++;
|
|
}
|
|
|
|
if( !*pMatch)
|
|
{
|
|
if( *pucSrc == '\0')
|
|
{
|
|
bFoundWord = FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
uiBytesToCopy = f_strlen( pucSrc);
|
|
|
|
if( uiBytesToCopy + 1 > uiMaxDestLen)
|
|
{
|
|
uiBytesToCopy = uiMaxDestLen - 1;
|
|
}
|
|
|
|
f_memcpy( pucDest, pucSrc, uiBytesToCopy + 1);
|
|
*puiPos = uiPos + uiBytesToCopy + 1;
|
|
}
|
|
else
|
|
{
|
|
// Copy the bytes between pucSrc and pMatch minus one
|
|
|
|
uiBytesToCopy = (FLMUINT) (pMatch - pucSrc);
|
|
|
|
if( uiBytesToCopy + 1 > uiMaxDestLen)
|
|
{
|
|
uiBytesToCopy = uiMaxDestLen - 1;
|
|
}
|
|
|
|
f_memcpy( pucDest, pucSrc, uiBytesToCopy );
|
|
pucDest[ uiBytesToCopy ] = '\0';
|
|
|
|
// Go past consuctive spaces
|
|
|
|
while( pucSrc[ ++uiBytesToCopy ] == NATIVE_SPACE)
|
|
{
|
|
uiBytesToCopy++;
|
|
}
|
|
|
|
*puiPos = uiPos + uiBytesToCopy;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return( bFoundWord);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Normalizes an internal string with possible formatting codes into
|
|
a NATIVE string. Drops all formatting codes and extended chars.
|
|
****************************************************************************/
|
|
FSTATIC void DDTextToNative(
|
|
FlmRecord * pRecord,
|
|
void * pvField,
|
|
char * pszBuffer,
|
|
FLMUINT uiBufLen,
|
|
FLMUINT * puiBufLen)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
pszBuffer[ 0] = 0;
|
|
|
|
if( pRecord->getDataLength( pvField))
|
|
{
|
|
if( RC_BAD( rc = pRecord->getNative( pvField, pszBuffer, &uiBufLen)))
|
|
{
|
|
if( rc != FERR_CONV_DEST_OVERFLOW)
|
|
{
|
|
pszBuffer[0] = 0;
|
|
uiBufLen = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uiBufLen = 0;
|
|
}
|
|
|
|
if( puiBufLen)
|
|
{
|
|
// Length needs to include the null byte
|
|
|
|
*puiBufLen = uiBufLen + 1;
|
|
}
|
|
|
|
return;
|
|
}
|