git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@1009 0109f412-320b-0410-ab79-c3e0c5ffbbe6
4702 lines
108 KiB
C++
4702 lines
108 KiB
C++
//-------------------------------------------------------------------------
|
|
// Desc: Routines for getting RFL information for the RFL viewer utility.
|
|
// Tabs: 3
|
|
//
|
|
// Copyright (c) 1998-2007 Novell, Inc. All Rights Reserved.
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; version 2.1
|
|
// of the License.
|
|
//
|
|
// This library 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
|
|
// Library Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; 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$
|
|
//------------------------------------------------------------------------------
|
|
|
|
#include "flaim.h"
|
|
#include "flaimsys.h"
|
|
#include "rflread.h"
|
|
|
|
// GEDCOM tag numbers for data to be returned
|
|
|
|
#define RFL_PACKET_FIELD 1
|
|
|
|
// Local function prototypes
|
|
|
|
FSTATIC void rflGetNumValue(
|
|
FLMBYTE * pucBuffer,
|
|
FLMUINT uiBufferLen,
|
|
FLMUINT uiNumOffset,
|
|
FLMUINT uiNumLen,
|
|
FLMUINT * puiNum,
|
|
FLMUINT * puiNumLen
|
|
);
|
|
|
|
FSTATIC void rflFormatTransID(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
);
|
|
|
|
FSTATIC void rflFormatTransIDs(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
);
|
|
|
|
FSTATIC void rflFormatIndex(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
);
|
|
|
|
FSTATIC void rflFormatContainer(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
);
|
|
|
|
FSTATIC void rflFormatDRN(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
);
|
|
|
|
FSTATIC void rflFormatEndBlockAddr(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp);
|
|
|
|
FSTATIC void rflFormatDRNRange(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp);
|
|
|
|
FSTATIC FLMUINT rflFindNextPacket(
|
|
FLMUINT uiStartOffset,
|
|
FLMBOOL bFindValidPacket);
|
|
|
|
FSTATIC FLMUINT rflFindPrevPacket(
|
|
FLMUINT uiStartOffset,
|
|
FLMBOOL bGoBackMoreThanOnePckt,
|
|
FLMBOOL bValidStartOffset);
|
|
|
|
FSTATIC RCODE rflRetrievePacket(
|
|
FLMUINT uiPrevPacketAddress,
|
|
FLMUINT uiFileOffset,
|
|
RFL_PACKET * pRflPacket);
|
|
|
|
FSTATIC RCODE rflGetNextOpPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
FLMBOOL * pbFoundNext);
|
|
|
|
FSTATIC RCODE rflGetPrevOpPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
FLMBOOL * pbFoundPrev);
|
|
|
|
FSTATIC RCODE rflPutNum(
|
|
F_Pool * pPool,
|
|
NODE * pLinkToNode,
|
|
FLMBOOL bPutAsSib,
|
|
eDispTag eDispTag,
|
|
FLMUINT uiNum,
|
|
FLMUINT uiOffset,
|
|
FLMUINT uiNumExpectedBytes,
|
|
FLMUINT uiNumBytes,
|
|
NODE ** ppNode);
|
|
|
|
FSTATIC RCODE rflExpandPacketHdr(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppParent);
|
|
|
|
FSTATIC RCODE rflExpandTrnsPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest);
|
|
|
|
FSTATIC RCODE rflExpandStartUnknownPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest);
|
|
|
|
FSTATIC RCODE rflExpandIndexSetPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest);
|
|
|
|
FSTATIC RCODE rflExpandBlkChainFreePacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest);
|
|
|
|
FSTATIC RCODE rflExpandReducePacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest);
|
|
|
|
FSTATIC RCODE rflExpandUpgradePacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest);
|
|
|
|
FSTATIC RCODE rflExpandIndexStatePacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest);
|
|
|
|
FSTATIC RCODE rflExpandDataPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
FLMBOOL bOutputPacket,
|
|
FLMUINT uiPacketType,
|
|
NODE ** ppDataPacketNode,
|
|
FLMUINT * puiDataLen,
|
|
FLMUINT * puiLevel);
|
|
|
|
FSTATIC RCODE rflExpandRecordPackets(
|
|
F_Pool * pPool,
|
|
FLMUINT uiOffset,
|
|
FLMUINT uiPacketType,
|
|
NODE ** ppLastPacketNode,
|
|
FLMUINT uiPacketOffset);
|
|
|
|
FSTATIC RCODE rflExpandChangeFieldsPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
FLMBOOL bOutputPacket,
|
|
NODE ** ppChangeFieldsPacketNode,
|
|
FLMUINT * puiDataLen);
|
|
|
|
FSTATIC RCODE rflExpandRecOpPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest,
|
|
FLMUINT uiPacketOffset);
|
|
|
|
FSTATIC RCODE rflExpandUnkPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest);
|
|
|
|
FSTATIC RCODE rflExpandEncryptionPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest);
|
|
|
|
FSTATIC RCODE rflExpandConfigSizePacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest);
|
|
|
|
FSTATIC void rflFormatCount(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp);
|
|
|
|
FSTATIC void rflFormatFlags(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp);
|
|
|
|
FSTATIC void rflFormatVersionRange(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp);
|
|
|
|
FSTATIC void rflFormatDBKeyLen(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp);
|
|
|
|
/********************************************************************
|
|
Desc: Get a value from a buffer at the specified offset.
|
|
*********************************************************************/
|
|
FSTATIC void rflGetNumValue(
|
|
FLMBYTE * pucBuffer,
|
|
FLMUINT uiBufferLen,
|
|
FLMUINT uiNumOffset,
|
|
FLMUINT uiNumLen,
|
|
FLMUINT * puiNum,
|
|
FLMUINT * puiNumLen
|
|
)
|
|
{
|
|
FLMBYTE uiTmp [4];
|
|
FLMUINT uiValidBytes;
|
|
FLMBYTE * pucNumBuf;
|
|
|
|
if (uiNumOffset + uiNumLen > uiBufferLen)
|
|
{
|
|
if (uiNumOffset >= uiBufferLen)
|
|
{
|
|
uiValidBytes = 0;
|
|
}
|
|
else
|
|
{
|
|
uiValidBytes = (FLMUINT)(uiBufferLen - uiNumOffset);
|
|
}
|
|
f_memset( uiTmp, 0, sizeof( uiTmp));
|
|
if (uiValidBytes)
|
|
{
|
|
f_memcpy( uiTmp, &pucBuffer [uiNumOffset], uiValidBytes);
|
|
}
|
|
pucNumBuf = &uiTmp [0];
|
|
}
|
|
else
|
|
{
|
|
pucNumBuf = &pucBuffer [uiNumOffset];
|
|
uiValidBytes = uiNumLen;
|
|
}
|
|
if (uiNumLen == 4)
|
|
{
|
|
*puiNum = (FLMUINT)FB2UD( pucNumBuf);
|
|
}
|
|
else if (uiNumLen == 2)
|
|
{
|
|
*puiNum = (FLMUINT)FB2UW( pucNumBuf);
|
|
}
|
|
else
|
|
{
|
|
*puiNum = *pucNumBuf;
|
|
}
|
|
if (puiNumLen)
|
|
{
|
|
*puiNumLen = uiValidBytes;
|
|
}
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Format a count
|
|
*********************************************************************/
|
|
FSTATIC void rflFormatCount(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
)
|
|
{
|
|
char * pszTmp = *ppszTmp;
|
|
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
if (pRflPacket->uiCountBytes == 4)
|
|
*pszTmp++ = ' ';
|
|
else
|
|
*pszTmp++ = '*';
|
|
f_sprintf( pszTmp, "CNT=%-10u ", (unsigned)pRflPacket->uiCount);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
*ppszTmp = pszTmp;
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Format flags
|
|
*********************************************************************/
|
|
FSTATIC void rflFormatFlags(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp)
|
|
{
|
|
char * pszTmp = *ppszTmp;
|
|
|
|
while (*pszTmp)
|
|
{
|
|
pszTmp++;
|
|
}
|
|
|
|
if (pRflPacket->uiFlagsBytes == 4)
|
|
{
|
|
*pszTmp++ = ' ';
|
|
}
|
|
else
|
|
{
|
|
*pszTmp++ = '*';
|
|
}
|
|
|
|
f_sprintf( pszTmp, "FLAGS=%-10u ", (unsigned)pRflPacket->uiFlags);
|
|
|
|
while (*pszTmp)
|
|
{
|
|
pszTmp++;
|
|
}
|
|
|
|
*ppszTmp = pszTmp;
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Format a transaction ID.
|
|
*********************************************************************/
|
|
FSTATIC void rflFormatTransID(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
)
|
|
{
|
|
char * pszTmp = *ppszTmp;
|
|
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
if (pRflPacket->uiTransIDBytes == 4)
|
|
*pszTmp++ = ' ';
|
|
else
|
|
*pszTmp++ = '*';
|
|
f_sprintf( pszTmp, "T=%-10u ", (unsigned)pRflPacket->uiTransID);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
*ppszTmp = pszTmp;
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Format a transaction IDs.
|
|
*********************************************************************/
|
|
FSTATIC void rflFormatTransIDs(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
)
|
|
{
|
|
char * pszTmp = *ppszTmp;
|
|
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
if (pRflPacket->uiTransIDBytes == 4)
|
|
*pszTmp++ = ' ';
|
|
else
|
|
*pszTmp++ = '*';
|
|
f_sprintf( pszTmp, "T=%-10u ", (unsigned)pRflPacket->uiTransID);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
|
|
if (pRflPacket->uiLastCommittedTransIDBytes == 4)
|
|
*pszTmp++ = ' ';
|
|
else
|
|
*pszTmp++ = '*';
|
|
f_sprintf( pszTmp, "LT=%-10u ",
|
|
(unsigned)pRflPacket->uiLastCommittedTransID);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
*ppszTmp = pszTmp;
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Format an index number
|
|
*********************************************************************/
|
|
FSTATIC void rflFormatIndex(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
)
|
|
{
|
|
char * pszTmp = *ppszTmp;
|
|
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
if (pRflPacket->uiIndexBytes == 2)
|
|
*pszTmp++ = ' ';
|
|
else
|
|
*pszTmp++ = '*';
|
|
f_sprintf( pszTmp, "I=%-5u ", (unsigned)pRflPacket->uiIndex);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
*ppszTmp = pszTmp;
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Format a container number
|
|
*********************************************************************/
|
|
FSTATIC void rflFormatContainer(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
)
|
|
{
|
|
char * pszTmp = *ppszTmp;
|
|
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
if (pRflPacket->uiContainerBytes == 2)
|
|
*pszTmp++ = ' ';
|
|
else
|
|
*pszTmp++ = '*';
|
|
f_sprintf( pszTmp, "C=%-5u ", (unsigned)pRflPacket->uiContainer);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
*ppszTmp = pszTmp;
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Format a DRN.
|
|
*********************************************************************/
|
|
FSTATIC void rflFormatDRN(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
)
|
|
{
|
|
char * pszTmp = *ppszTmp;
|
|
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
if (pRflPacket->uiDrnBytes == 4)
|
|
*pszTmp++ = ' ';
|
|
else
|
|
*pszTmp++ = '*';
|
|
f_sprintf( pszTmp, "D=%-9u (%08X) ", (unsigned)pRflPacket->uiDrn,
|
|
(unsigned)pRflPacket->uiDrn);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
*ppszTmp = pszTmp;
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Format an ending block address
|
|
*********************************************************************/
|
|
FSTATIC void rflFormatEndBlockAddr(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp)
|
|
{
|
|
char * pszTmp = *ppszTmp;
|
|
|
|
while (*pszTmp)
|
|
{
|
|
pszTmp++;
|
|
}
|
|
|
|
if (pRflPacket->uiEndDrnBytes == 4)
|
|
{
|
|
*pszTmp++ = ' ';
|
|
}
|
|
else
|
|
{
|
|
*pszTmp++ = '*';
|
|
}
|
|
|
|
f_sprintf( pszTmp, "B=%-9u (%08X) ", (unsigned)pRflPacket->uiEndDrn,
|
|
(unsigned)pRflPacket->uiEndDrn);
|
|
|
|
while (*pszTmp)
|
|
{
|
|
pszTmp++;
|
|
}
|
|
|
|
*ppszTmp = pszTmp;
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Format version range
|
|
*********************************************************************/
|
|
FSTATIC void rflFormatVersionRange(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
)
|
|
{
|
|
char * pszTmp = *ppszTmp;
|
|
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
f_sprintf( pszTmp, " OLD=");
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
if (pRflPacket->uiDrnBytes != 4)
|
|
{
|
|
*pszTmp++ = '*';
|
|
}
|
|
f_sprintf( pszTmp, "%u, NEW=", (unsigned)pRflPacket->uiDrn);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
|
|
if (pRflPacket->uiEndDrnBytes != 4)
|
|
{
|
|
*pszTmp++ = '*';
|
|
}
|
|
f_sprintf( pszTmp, "%u", (unsigned)pRflPacket->uiEndDrn);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
*ppszTmp = pszTmp;
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Format Database Key Length
|
|
*********************************************************************/
|
|
FSTATIC void rflFormatDBKeyLen(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
)
|
|
{
|
|
char * pszTmp = *ppszTmp;
|
|
|
|
if (pRflPacket->uiEndDrn < FLM_FILE_FORMAT_VER_4_60)
|
|
{
|
|
return;
|
|
}
|
|
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
f_sprintf( pszTmp, " DBKeyLen=");
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
if (pRflPacket->uiCountBytes != 2)
|
|
{
|
|
*pszTmp++ = '*';
|
|
}
|
|
f_sprintf( pszTmp, "%u", (unsigned)pRflPacket->uiCount);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
*ppszTmp = pszTmp;
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Format DRN range
|
|
*********************************************************************/
|
|
FSTATIC void rflFormatDRNRange(
|
|
RFL_PACKET * pRflPacket,
|
|
char ** ppszTmp
|
|
)
|
|
{
|
|
char * pszTmp = *ppszTmp;
|
|
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
f_sprintf( pszTmp, " D=");
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
if (pRflPacket->uiDrnBytes != 4)
|
|
{
|
|
*pszTmp++ = '*';
|
|
}
|
|
f_sprintf( pszTmp, "%u to ", (unsigned)pRflPacket->uiDrn);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
|
|
if (pRflPacket->uiEndDrnBytes != 4)
|
|
{
|
|
*pszTmp++ = '*';
|
|
}
|
|
f_sprintf( pszTmp, "%u", (unsigned)pRflPacket->uiEndDrn);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
*ppszTmp = pszTmp;
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Format a display buffer given an operation sub-tree
|
|
*********************************************************************/
|
|
void RflFormatPacket(
|
|
void * pPacket,
|
|
char * pszDispBuffer
|
|
)
|
|
{
|
|
RFL_PACKET * pRflPacket = (RFL_PACKET *)pPacket;
|
|
char * pszTmp;
|
|
|
|
// Format the data into our display buffer.
|
|
|
|
pszTmp = pszDispBuffer;
|
|
f_sprintf( pszTmp, "%08X ", (unsigned)pRflPacket->uiFileOffset);
|
|
while (*pszTmp)
|
|
pszTmp++;
|
|
|
|
// If the packet address does not match, set packet type to unknown.
|
|
|
|
if (!pRflPacket->bValidPacketType)
|
|
{
|
|
if (pRflPacket->bHavePacketType)
|
|
{
|
|
f_sprintf( pszTmp, "Unk (%02X) ",
|
|
(unsigned)pRflPacket->uiPacketType);
|
|
}
|
|
else
|
|
{
|
|
f_strcpy( pszTmp, "Unk (None) ");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (pRflPacket->uiPacketType)
|
|
{
|
|
case RFL_TRNS_BEGIN_PACKET:
|
|
f_strcpy( pszTmp, "BeginTrans ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_TRNS_BEGIN_EX_PACKET:
|
|
f_strcpy( pszTmp, "BeginTransEx ");
|
|
rflFormatTransIDs( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_TRNS_COMMIT_PACKET:
|
|
f_strcpy( pszTmp, "CommitTrans ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_TRNS_ABORT_PACKET:
|
|
f_strcpy( pszTmp, "AbortTrans ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_ADD_RECORD_PACKET:
|
|
f_strcpy( pszTmp, " AddRecord ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatContainer( pRflPacket, &pszTmp);
|
|
rflFormatDRN( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_ADD_RECORD_PACKET_VER_2:
|
|
f_strcpy( pszTmp, " AddRecord2 ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatContainer( pRflPacket, &pszTmp);
|
|
rflFormatDRN( pRflPacket, &pszTmp);
|
|
rflFormatFlags( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_MODIFY_RECORD_PACKET:
|
|
f_strcpy( pszTmp, " ModRecord ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatContainer( pRflPacket, &pszTmp);
|
|
rflFormatDRN( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_MODIFY_RECORD_PACKET_VER_2:
|
|
f_strcpy( pszTmp, " ModRecord ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatContainer( pRflPacket, &pszTmp);
|
|
rflFormatDRN( pRflPacket, &pszTmp);
|
|
rflFormatFlags( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_DELETE_RECORD_PACKET:
|
|
f_strcpy( pszTmp, " DelRecord ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatContainer( pRflPacket, &pszTmp);
|
|
rflFormatDRN( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_DELETE_RECORD_PACKET_VER_2:
|
|
f_strcpy( pszTmp, " DelRecord ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatContainer( pRflPacket, &pszTmp);
|
|
rflFormatDRN( pRflPacket, &pszTmp);
|
|
rflFormatFlags( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_RESERVE_DRN_PACKET:
|
|
f_strcpy( pszTmp, " ReserveDRN ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatContainer( pRflPacket, &pszTmp);
|
|
rflFormatDRN( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_CHANGE_FIELDS_PACKET:
|
|
f_strcpy( pszTmp, " ChgFlds ");
|
|
break;
|
|
case RFL_DATA_RECORD_PACKET:
|
|
f_strcpy( pszTmp, " DataRec ");
|
|
break;
|
|
case RFL_ENC_DATA_RECORD_PACKET:
|
|
f_strcpy( pszTmp, " EDataRec ");
|
|
break;
|
|
case RFL_DATA_RECORD_PACKET_VER_3:
|
|
f_strcpy( pszTmp, " DataRec3 ");
|
|
break;
|
|
case RFL_INDEX_SET_PACKET:
|
|
f_strcpy( pszTmp, " IndexSet ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatIndex( pRflPacket, &pszTmp);
|
|
rflFormatDRNRange( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_INDEX_SET_PACKET_VER_2:
|
|
f_strcpy( pszTmp, " IndexSet2 ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatContainer( pRflPacket, &pszTmp);
|
|
rflFormatIndex( pRflPacket, &pszTmp);
|
|
rflFormatDRNRange( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_BLK_CHAIN_FREE_PACKET:
|
|
f_strcpy( pszTmp, "BlkChainFree ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatDRN( pRflPacket, &pszTmp);
|
|
rflFormatCount( pRflPacket, &pszTmp);
|
|
rflFormatEndBlockAddr( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_START_UNKNOWN_PACKET:
|
|
f_strcpy( pszTmp, " StartUnk ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_UNKNOWN_PACKET:
|
|
f_strcpy( pszTmp, " UserUnk ");
|
|
break;
|
|
case RFL_REDUCE_PACKET:
|
|
f_strcpy( pszTmp, "Reduce ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatCount( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_UPGRADE_PACKET:
|
|
f_strcpy( pszTmp, "Upgrade ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatVersionRange( pRflPacket, &pszTmp);
|
|
rflFormatDBKeyLen( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_INDEX_SUSPEND_PACKET:
|
|
f_strcpy( pszTmp, "Index Suspend ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatIndex( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_INDEX_RESUME_PACKET:
|
|
f_strcpy( pszTmp, "Index Resume ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatIndex( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_WRAP_KEY_PACKET:
|
|
f_strcpy( pszTmp, "Wrap Key ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatDBKeyLen( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_ENABLE_ENCRYPTION_PACKET:
|
|
f_strcpy( pszTmp, "Enable Enc ");
|
|
rflFormatTransID( pRflPacket, &pszTmp);
|
|
rflFormatDBKeyLen( pRflPacket, &pszTmp);
|
|
break;
|
|
case RFL_CONFIG_SIZE_EVENT_PACKET:
|
|
f_strcpy( pszTmp, "Config Size ");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Find the next packet in the RFL file starting from the
|
|
specified start offset. This routine will NOT go more than
|
|
a packet body length worth down. If it cannot find what looks
|
|
like a valid packet by then, it will just return the start
|
|
offset that was passed in.
|
|
*********************************************************************/
|
|
FSTATIC FLMUINT rflFindNextPacket(
|
|
FLMUINT uiStartOffset,
|
|
FLMBOOL bFindValidPacket
|
|
)
|
|
{
|
|
RCODE rc;
|
|
FLMUINT uiNextAddr;
|
|
FLMBYTE * pucPacketHdr = NULL;
|
|
FLMBYTE * pucBuffer = NULL;
|
|
FLMUINT uiBytesToRead;
|
|
FLMUINT uiBytesRead;
|
|
RFL_PACKET RflPacket;
|
|
|
|
uiBytesToRead = (FLMUINT)((bFindValidPacket)
|
|
? (FLMUINT)RFL_MAX_PACKET_SIZE
|
|
: (FLMUINT)RFL_MAX_PACKET_BODY_SIZE);
|
|
if (RC_BAD( rc = f_calloc(
|
|
uiBytesToRead, &pucBuffer)))
|
|
{
|
|
uiNextAddr = 0;
|
|
goto Exit;
|
|
}
|
|
pucPacketHdr = pucBuffer;
|
|
|
|
// Read up to a full packet body.
|
|
|
|
rc = gv_pRflFileHdl->read( uiStartOffset,
|
|
uiBytesToRead, pucPacketHdr, &uiBytesRead);
|
|
if (RC_BAD( rc))
|
|
{
|
|
if (rc != FERR_IO_END_OF_FILE || !uiBytesRead)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
uiNextAddr = 0;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Go until we something where the packet address matches the
|
|
// file offset.
|
|
|
|
uiNextAddr = uiStartOffset;
|
|
while (uiBytesRead >= 4)
|
|
{
|
|
if ((FLMUINT)FB2UD( pucPacketHdr) == uiNextAddr)
|
|
{
|
|
if (!bFindValidPacket)
|
|
break;
|
|
|
|
// See if this is a valid packet
|
|
|
|
if ((RC_OK( rflRetrievePacket( 0, uiNextAddr, &RflPacket))) &&
|
|
(RflPacket.bValidPacketType))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
pucPacketHdr++;
|
|
uiNextAddr++;
|
|
uiBytesRead--;
|
|
}
|
|
|
|
// If we couldn't get a matching address, simply return
|
|
// the start address that was passed in.
|
|
|
|
if (uiBytesRead < 4)
|
|
{
|
|
uiNextAddr = (FLMUINT)((bFindValidPacket)
|
|
? (FLMUINT)0
|
|
: uiStartOffset);
|
|
}
|
|
Exit:
|
|
if (pucBuffer)
|
|
{
|
|
f_free( &pucBuffer);
|
|
}
|
|
return( uiNextAddr);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Find the previous packet in the RFL file starting from the
|
|
specified start offset. This routine will NOT go more than
|
|
a packet length worth back. If it cannot find what looks
|
|
like a valid packet by then, it will just return the start
|
|
offset that was passed in.
|
|
*********************************************************************/
|
|
FSTATIC FLMUINT rflFindPrevPacket(
|
|
FLMUINT uiStartOffset,
|
|
FLMBOOL bGoBackMoreThanOnePckt,
|
|
FLMBOOL bValidStartOffset
|
|
)
|
|
{
|
|
RCODE rc;
|
|
FLMUINT uiPrevAddr = 0;
|
|
FLMUINT uiReadOffset;
|
|
FLMBYTE * pucPacketHdr = NULL;
|
|
FLMBYTE * pucBuffer = NULL;
|
|
FLMUINT uiBytesToRead;
|
|
FLMUINT uiBytesRead;
|
|
FLMUINT uiBestCandidate;
|
|
RFL_PACKET RflPacket;
|
|
|
|
Get_Prev_Packet:
|
|
|
|
if (uiStartOffset <= 512)
|
|
{
|
|
uiPrevAddr = 0;
|
|
goto Exit;
|
|
}
|
|
|
|
// Read up to a full packet
|
|
|
|
uiReadOffset = (FLMUINT)((uiStartOffset >
|
|
(FLMUINT)(RFL_MAX_PACKET_SIZE + 512))
|
|
? (FLMUINT)(uiStartOffset -
|
|
RFL_MAX_PACKET_SIZE)
|
|
: (FLMUINT)512);
|
|
if (uiStartOffset - uiReadOffset <= 4)
|
|
{
|
|
uiPrevAddr = uiReadOffset;
|
|
goto Exit;
|
|
}
|
|
|
|
if (pucBuffer)
|
|
{
|
|
f_free( &pucBuffer);
|
|
}
|
|
uiBytesToRead = uiStartOffset - uiReadOffset;
|
|
if (RC_BAD( rc = f_calloc( uiBytesToRead, &pucBuffer)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pucPacketHdr = pucBuffer;
|
|
|
|
rc = gv_pRflFileHdl->read( uiReadOffset,
|
|
uiBytesToRead, pucPacketHdr, &uiBytesRead);
|
|
if (RC_BAD( rc))
|
|
{
|
|
if (rc != FERR_IO_END_OF_FILE)
|
|
{
|
|
uiPrevAddr = 0;
|
|
goto Exit;
|
|
}
|
|
}
|
|
else if (uiBytesRead != uiBytesToRead)
|
|
{
|
|
uiPrevAddr = uiStartOffset - 4;
|
|
goto Exit;
|
|
}
|
|
|
|
// Go until we something where the packet address matches the
|
|
// file offset.
|
|
|
|
uiBestCandidate =
|
|
uiPrevAddr = uiStartOffset - 4;
|
|
uiBytesRead -= 4;
|
|
pucPacketHdr += uiBytesRead;
|
|
for (;;)
|
|
{
|
|
if ((FLMUINT)FB2UD( pucPacketHdr) == uiPrevAddr)
|
|
{
|
|
if (uiBestCandidate != uiStartOffset - 4)
|
|
{
|
|
uiBestCandidate = uiPrevAddr;
|
|
}
|
|
|
|
// See if this is a real packet whose next address is
|
|
// the same as uiStartOffset.
|
|
|
|
if (RC_BAD( rflRetrievePacket( 0, uiPrevAddr, &RflPacket)))
|
|
{
|
|
uiPrevAddr = uiStartOffset - 4;
|
|
goto Exit;
|
|
}
|
|
|
|
// If we have a valid packet type and the packet's
|
|
// next packet address is the same as the start
|
|
// offset we passed in, we have a packet.
|
|
|
|
if (RflPacket.bValidPacketType)
|
|
{
|
|
if ((!bValidStartOffset) ||
|
|
(RflPacket.uiNextPacketAddress == uiStartOffset))
|
|
{
|
|
break;
|
|
}
|
|
else if (RflPacket.uiNextPacketAddress < uiStartOffset)
|
|
{
|
|
uiPrevAddr = uiBestCandidate;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!uiBytesRead)
|
|
{
|
|
if ((uiBestCandidate != uiStartOffset - 4) ||
|
|
(!bGoBackMoreThanOnePckt))
|
|
{
|
|
uiPrevAddr = uiBestCandidate;
|
|
goto Exit;
|
|
}
|
|
uiStartOffset = uiReadOffset;
|
|
goto Get_Prev_Packet;
|
|
}
|
|
pucPacketHdr--;
|
|
uiBytesRead--;
|
|
uiPrevAddr--;
|
|
}
|
|
Exit:
|
|
if( pucBuffer)
|
|
{
|
|
f_free( &pucBuffer);
|
|
}
|
|
return( uiPrevAddr);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Retrieves the packet at the specified file offset.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflRetrievePacket(
|
|
FLMUINT uiPrevPacketAddress,
|
|
FLMUINT uiFileOffset,
|
|
RFL_PACKET * pRflPacket
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
FLMUINT uiBytesToRead;
|
|
FLMUINT uiBytesRead;
|
|
FLMUINT uiBytes;
|
|
FLMUINT uiExpectedBodyLen = 0;
|
|
FLMBYTE * pucPacketHdr;
|
|
FLMBYTE * pucPacketBody = NULL;
|
|
|
|
f_memset( pRflPacket, 0, sizeof( RFL_PACKET));
|
|
pRflPacket->uiFileOffset = uiFileOffset;
|
|
pRflPacket->uiPrevPacketAddress = uiPrevPacketAddress;
|
|
|
|
// Read the packet header.
|
|
|
|
pucPacketHdr = &gv_rflBuffer [0];
|
|
uiBytesToRead = RFL_PACKET_OVERHEAD;
|
|
if (RC_BAD( rc = gv_pRflFileHdl->read( uiFileOffset,
|
|
uiBytesToRead, pucPacketHdr, &uiBytesRead)))
|
|
{
|
|
if (rc != FERR_IO_END_OF_FILE)
|
|
{
|
|
goto Exit;
|
|
}
|
|
else
|
|
{
|
|
if (!uiBytesRead)
|
|
{
|
|
goto Exit;
|
|
}
|
|
rc = FERR_OK;
|
|
}
|
|
}
|
|
|
|
// Extract values from the packet header.
|
|
|
|
rflGetNumValue( pucPacketHdr, uiBytesRead, RFL_PACKET_ADDRESS_OFFSET,
|
|
4, &pRflPacket->uiPacketAddress,
|
|
&pRflPacket->uiPacketAddressBytes);
|
|
|
|
rflGetNumValue( pucPacketHdr, uiBytesRead, RFL_PACKET_CHECKSUM_OFFSET,
|
|
1, &pRflPacket->uiPacketChecksum, &uiBytes);
|
|
pRflPacket->bHavePacketChecksum = (FLMBOOL)((uiBytes)
|
|
? (FLMBOOL)TRUE : (FLMBOOL)FALSE);
|
|
|
|
rflGetNumValue( pucPacketHdr, uiBytesRead, RFL_PACKET_TYPE_OFFSET,
|
|
1, &pRflPacket->uiPacketType, &uiBytes);
|
|
pRflPacket->bValidPacketType =
|
|
pRflPacket->bHavePacketType = (FLMBOOL)((uiBytes)
|
|
? (FLMBOOL)TRUE : (FLMBOOL)FALSE);
|
|
|
|
rflGetNumValue( pucPacketHdr, uiBytesRead, RFL_PACKET_BODY_LENGTH_OFFSET,
|
|
2, &pRflPacket->uiPacketBodyLength,
|
|
&pRflPacket->uiPacketBodyLengthBytes);
|
|
|
|
// If the packet address does not match, set bValidPacketType to FALSE
|
|
|
|
if ((!pRflPacket->bHavePacketType) ||
|
|
(pRflPacket->uiPacketAddressBytes < 4) ||
|
|
(pRflPacket->uiPacketAddress != uiFileOffset))
|
|
{
|
|
pRflPacket->bValidPacketType = FALSE;
|
|
if (uiBytesRead < RFL_PACKET_OVERHEAD)
|
|
{
|
|
pRflPacket->uiNextPacketAddress = 0;
|
|
}
|
|
else if (pRflPacket->uiPacketAddress == uiFileOffset)
|
|
{
|
|
pRflPacket->uiNextPacketAddress =
|
|
rflFindNextPacket( uiFileOffset + RFL_PACKET_OVERHEAD,
|
|
FALSE);
|
|
}
|
|
else
|
|
{
|
|
pRflPacket->uiNextPacketAddress =
|
|
rflFindNextPacket( uiFileOffset + 1, FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pRflPacket->bHaveTimes =
|
|
(FLMBOOL)((pRflPacket->uiPacketType & RFL_TIME_LOGGED_FLAG)
|
|
? (FLMBOOL)TRUE
|
|
: (FLMBOOL)FALSE);
|
|
pRflPacket->uiPacketType &= RFL_PACKET_TYPE_MASK;
|
|
switch (pRflPacket->uiPacketType)
|
|
{
|
|
case RFL_TRNS_BEGIN_PACKET:
|
|
uiExpectedBodyLen = 8;
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
uiExpectedBodyLen += 4;
|
|
}
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_TRNS_BEGIN_EX_PACKET:
|
|
uiExpectedBodyLen = 12;
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
uiExpectedBodyLen += 4;
|
|
}
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_TRNS_COMMIT_PACKET:
|
|
case RFL_TRNS_ABORT_PACKET:
|
|
uiExpectedBodyLen = 8;
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
uiExpectedBodyLen += 8;
|
|
}
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_ADD_RECORD_PACKET:
|
|
case RFL_MODIFY_RECORD_PACKET:
|
|
case RFL_DELETE_RECORD_PACKET:
|
|
case RFL_RESERVE_DRN_PACKET:
|
|
uiExpectedBodyLen = 10;
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
uiExpectedBodyLen += 16;
|
|
}
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_ADD_RECORD_PACKET_VER_2:
|
|
case RFL_MODIFY_RECORD_PACKET_VER_2:
|
|
case RFL_DELETE_RECORD_PACKET_VER_2:
|
|
uiExpectedBodyLen = 11;
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
uiExpectedBodyLen += 16;
|
|
}
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_CHANGE_FIELDS_PACKET:
|
|
case RFL_DATA_RECORD_PACKET:
|
|
case RFL_ENC_DATA_RECORD_PACKET:
|
|
case RFL_DATA_RECORD_PACKET_VER_3:
|
|
case RFL_UNKNOWN_PACKET:
|
|
uiExpectedBodyLen = pRflPacket->uiPacketBodyLength;
|
|
if (uiExpectedBodyLen & 0x03)
|
|
{
|
|
uiExpectedBodyLen += (4 - (uiExpectedBodyLen & 0x0003));
|
|
}
|
|
if (uiExpectedBodyLen > RFL_MAX_PACKET_BODY_SIZE)
|
|
{
|
|
uiExpectedBodyLen = RFL_MAX_PACKET_BODY_SIZE;
|
|
}
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_INDEX_SET_PACKET:
|
|
uiExpectedBodyLen = 14;
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
uiExpectedBodyLen += 16;
|
|
}
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_INDEX_SET_PACKET_VER_2:
|
|
uiExpectedBodyLen = 16;
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
uiExpectedBodyLen += 16;
|
|
}
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_BLK_CHAIN_FREE_PACKET:
|
|
uiExpectedBodyLen = 16;
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
uiExpectedBodyLen += 16;
|
|
}
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_START_UNKNOWN_PACKET:
|
|
uiExpectedBodyLen = 4;
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_REDUCE_PACKET:
|
|
uiExpectedBodyLen = 8;
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_UPGRADE_PACKET:
|
|
uiExpectedBodyLen = pRflPacket->uiPacketBodyLengthBytes;
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_INDEX_SUSPEND_PACKET:
|
|
case RFL_INDEX_RESUME_PACKET:
|
|
uiExpectedBodyLen = 6;
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
uiExpectedBodyLen += 8;
|
|
}
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
case RFL_WRAP_KEY_PACKET:
|
|
case RFL_ENABLE_ENCRYPTION_PACKET:
|
|
uiExpectedBodyLen = pRflPacket->uiPacketBodyLength;
|
|
break;
|
|
case RFL_CONFIG_SIZE_EVENT_PACKET:
|
|
uiExpectedBodyLen = 16;
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
uiExpectedBodyLen;
|
|
break;
|
|
default:
|
|
pRflPacket->bValidPacketType = FALSE;
|
|
pRflPacket->uiNextPacketAddress =
|
|
rflFindNextPacket( uiFileOffset + RFL_PACKET_OVERHEAD,
|
|
FALSE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Get the rest of the packet.
|
|
// Adjust the packet body length if the packet is encrypted.
|
|
|
|
pRflPacket->bValidChecksum = FALSE;
|
|
if (uiBytesRead < RFL_PACKET_OVERHEAD || !pRflPacket->bValidPacketType)
|
|
{
|
|
uiBytesRead = 0;
|
|
}
|
|
else
|
|
{
|
|
pucPacketBody = &gv_rflBuffer [RFL_PACKET_OVERHEAD];
|
|
if (RC_BAD( rc = gv_pRflFileHdl->read( uiFileOffset + RFL_PACKET_OVERHEAD,
|
|
uiExpectedBodyLen, pucPacketBody, &uiBytesRead)))
|
|
{
|
|
if (rc != FERR_IO_END_OF_FILE)
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
pRflPacket->bValidChecksum = TRUE;
|
|
|
|
// For change field and data record packets, if we didn't
|
|
// read everything, or the checksum doesn't verify,
|
|
// determine where the next packet starts, starting from
|
|
// the packet overhead.
|
|
|
|
if (pRflPacket->uiPacketType == RFL_CHANGE_FIELDS_PACKET ||
|
|
pRflPacket->uiPacketType == RFL_DATA_RECORD_PACKET ||
|
|
pRflPacket->uiPacketType == RFL_ENC_DATA_RECORD_PACKET ||
|
|
pRflPacket->uiPacketType == RFL_DATA_RECORD_PACKET_VER_3)
|
|
{
|
|
if ((uiBytesRead != uiExpectedBodyLen) ||
|
|
(!pRflPacket->bHavePacketChecksum) ||
|
|
(RflCalcChecksum( gv_rflBuffer,
|
|
uiExpectedBodyLen) !=
|
|
pRflPacket->uiPacketChecksum))
|
|
{
|
|
pRflPacket->bValidChecksum = FALSE;
|
|
pRflPacket->uiNextPacketAddress =
|
|
rflFindNextPacket( uiFileOffset + RFL_PACKET_OVERHEAD,
|
|
FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((uiBytesRead != uiExpectedBodyLen) ||
|
|
(!pRflPacket->bHavePacketChecksum) ||
|
|
(RflCalcChecksum( gv_rflBuffer, uiExpectedBodyLen) !=
|
|
pRflPacket->uiPacketChecksum))
|
|
{
|
|
pRflPacket->bValidChecksum = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get the packet information we want to keep
|
|
|
|
switch (pRflPacket->uiPacketType)
|
|
{
|
|
case RFL_TRNS_BEGIN_PACKET:
|
|
case RFL_TRNS_BEGIN_EX_PACKET:
|
|
|
|
// Get transaction ID
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
|
|
// Get start seconds - also serves as KEY 2 for encryption
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 4,
|
|
4, &pRflPacket->uiStartSeconds,
|
|
&pRflPacket->uiStartSecondsBytes);
|
|
|
|
// Get the last committed transaction ID
|
|
|
|
if( pRflPacket->uiPacketType == RFL_TRNS_BEGIN_EX_PACKET)
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 8,
|
|
4, &pRflPacket->uiLastCommittedTransID,
|
|
&pRflPacket->uiLastCommittedTransIDBytes);
|
|
}
|
|
|
|
// Get start microseconds
|
|
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
if( pRflPacket->uiPacketType == RFL_TRNS_BEGIN_EX_PACKET)
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 12,
|
|
4, &pRflPacket->uiStartMicro,
|
|
&pRflPacket->uiStartMicroBytes);
|
|
}
|
|
else
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 8,
|
|
4, &pRflPacket->uiStartMicro,
|
|
&pRflPacket->uiStartMicroBytes);
|
|
}
|
|
}
|
|
break;
|
|
case RFL_TRNS_COMMIT_PACKET:
|
|
case RFL_TRNS_ABORT_PACKET:
|
|
|
|
// Get transaction ID
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
|
|
// Get transaction begin offset in file.
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 4,
|
|
4, &pRflPacket->uiTransStartAddr,
|
|
&pRflPacket->uiTransStartAddrBytes);
|
|
|
|
// Get start time and start microseconds.
|
|
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 8,
|
|
4, &pRflPacket->uiStartSeconds,
|
|
&pRflPacket->uiStartSecondsBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 12,
|
|
4, &pRflPacket->uiStartMicro,
|
|
&pRflPacket->uiStartMicroBytes);
|
|
}
|
|
break;
|
|
case RFL_ADD_RECORD_PACKET:
|
|
case RFL_MODIFY_RECORD_PACKET:
|
|
case RFL_DELETE_RECORD_PACKET:
|
|
case RFL_RESERVE_DRN_PACKET:
|
|
|
|
// Get transaction ID
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
|
|
// Get the container
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 4,
|
|
2, &pRflPacket->uiContainer,
|
|
&pRflPacket->uiContainerBytes);
|
|
|
|
// Get DRN
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 6,
|
|
4, &pRflPacket->uiDrn,
|
|
&pRflPacket->uiDrnBytes);
|
|
|
|
// Get start and time and microseconds.
|
|
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 10,
|
|
4, &pRflPacket->uiStartSeconds,
|
|
&pRflPacket->uiStartSecondsBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 14,
|
|
4, &pRflPacket->uiStartMicro,
|
|
&pRflPacket->uiStartMicroBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 18,
|
|
4, &pRflPacket->uiEndSeconds,
|
|
&pRflPacket->uiEndSecondsBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 22,
|
|
4, &pRflPacket->uiEndMicro,
|
|
&pRflPacket->uiEndMicroBytes);
|
|
}
|
|
break;
|
|
|
|
case RFL_ADD_RECORD_PACKET_VER_2:
|
|
case RFL_MODIFY_RECORD_PACKET_VER_2:
|
|
case RFL_DELETE_RECORD_PACKET_VER_2:
|
|
// Get transaction ID
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
|
|
// Get the container
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 4,
|
|
2, &pRflPacket->uiContainer,
|
|
&pRflPacket->uiContainerBytes);
|
|
|
|
// Get DRN
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 6,
|
|
4, &pRflPacket->uiDrn,
|
|
&pRflPacket->uiDrnBytes);
|
|
|
|
// Get flags
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 10,
|
|
4, &pRflPacket->uiFlags,
|
|
&pRflPacket->uiFlagsBytes);
|
|
|
|
// Get start and time and microseconds.
|
|
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 10,
|
|
4, &pRflPacket->uiStartSeconds,
|
|
&pRflPacket->uiStartSecondsBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 14,
|
|
4, &pRflPacket->uiStartMicro,
|
|
&pRflPacket->uiStartMicroBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 18,
|
|
4, &pRflPacket->uiEndSeconds,
|
|
&pRflPacket->uiEndSecondsBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 22,
|
|
4, &pRflPacket->uiEndMicro,
|
|
&pRflPacket->uiEndMicroBytes);
|
|
}
|
|
break;
|
|
|
|
case RFL_INDEX_SET_PACKET:
|
|
|
|
// Get transaction ID
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
|
|
// Get index number
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 4,
|
|
2, &pRflPacket->uiIndex,
|
|
&pRflPacket->uiIndexBytes);
|
|
|
|
// Get start and end drns
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 6,
|
|
4, &pRflPacket->uiDrn,
|
|
&pRflPacket->uiDrnBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 10,
|
|
4, &pRflPacket->uiEndDrn,
|
|
&pRflPacket->uiEndDrnBytes);
|
|
|
|
// Get start microseconds
|
|
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 14,
|
|
4, &pRflPacket->uiStartSeconds,
|
|
&pRflPacket->uiStartSecondsBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 18,
|
|
4, &pRflPacket->uiStartMicro,
|
|
&pRflPacket->uiStartMicroBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 22,
|
|
4, &pRflPacket->uiEndSeconds,
|
|
&pRflPacket->uiEndSecondsBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 26,
|
|
4, &pRflPacket->uiEndMicro,
|
|
&pRflPacket->uiEndMicroBytes);
|
|
}
|
|
break;
|
|
case RFL_INDEX_SET_PACKET_VER_2:
|
|
|
|
// Get transaction ID
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
|
|
// Get container number
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 4,
|
|
2, &pRflPacket->uiContainer,
|
|
&pRflPacket->uiContainerBytes);
|
|
|
|
// Get index number
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 6,
|
|
2, &pRflPacket->uiIndex,
|
|
&pRflPacket->uiIndexBytes);
|
|
|
|
// Get start and end drns
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 8,
|
|
4, &pRflPacket->uiDrn,
|
|
&pRflPacket->uiDrnBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 12,
|
|
4, &pRflPacket->uiEndDrn,
|
|
&pRflPacket->uiEndDrnBytes);
|
|
|
|
// Get start microseconds
|
|
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 16,
|
|
4, &pRflPacket->uiStartSeconds,
|
|
&pRflPacket->uiStartSecondsBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 20,
|
|
4, &pRflPacket->uiStartMicro,
|
|
&pRflPacket->uiStartMicroBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 24,
|
|
4, &pRflPacket->uiEndSeconds,
|
|
&pRflPacket->uiEndSecondsBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 28,
|
|
4, &pRflPacket->uiEndMicro,
|
|
&pRflPacket->uiEndMicroBytes);
|
|
}
|
|
break;
|
|
case RFL_BLK_CHAIN_FREE_PACKET:
|
|
|
|
// Get transaction ID
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
|
|
// Get the tracker record number
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 4,
|
|
4, &pRflPacket->uiDrn,
|
|
&pRflPacket->uiDrnBytes);
|
|
|
|
// Get the block count
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 8,
|
|
4, &pRflPacket->uiCount,
|
|
&pRflPacket->uiCountBytes);
|
|
|
|
// Get the ending block address
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 12,
|
|
4, &pRflPacket->uiEndDrn,
|
|
&pRflPacket->uiEndDrnBytes);
|
|
|
|
// Get start microseconds
|
|
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 16,
|
|
4, &pRflPacket->uiStartSeconds,
|
|
&pRflPacket->uiStartSecondsBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 20,
|
|
4, &pRflPacket->uiStartMicro,
|
|
&pRflPacket->uiStartMicroBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 24,
|
|
4, &pRflPacket->uiEndSeconds,
|
|
&pRflPacket->uiEndSecondsBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 28,
|
|
4, &pRflPacket->uiEndMicro,
|
|
&pRflPacket->uiEndMicroBytes);
|
|
}
|
|
break;
|
|
case RFL_START_UNKNOWN_PACKET:
|
|
|
|
// Get transaction ID
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
break;
|
|
|
|
case RFL_REDUCE_PACKET:
|
|
|
|
// Get transaction ID and count
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 4,
|
|
4, &pRflPacket->uiCount,
|
|
&pRflPacket->uiCountBytes);
|
|
break;
|
|
|
|
case RFL_UPGRADE_PACKET:
|
|
|
|
// Get transaction ID
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
|
|
// Get old and new version numbers
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 4,
|
|
4, &pRflPacket->uiDrn,
|
|
&pRflPacket->uiDrnBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 8,
|
|
4, &pRflPacket->uiEndDrn,
|
|
&pRflPacket->uiEndDrnBytes);
|
|
if (pRflPacket->uiEndDrn >= FLM_FILE_FORMAT_VER_4_60)
|
|
{
|
|
// Get the size of the DB key.
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 12,
|
|
2, &pRflPacket->uiCount,
|
|
&pRflPacket->uiCountBytes);
|
|
}
|
|
break;
|
|
case RFL_INDEX_SUSPEND_PACKET:
|
|
case RFL_INDEX_RESUME_PACKET:
|
|
|
|
// Get transaction ID
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
|
|
// Get index number
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 4,
|
|
2, &pRflPacket->uiIndex,
|
|
&pRflPacket->uiIndexBytes);
|
|
break;
|
|
case RFL_WRAP_KEY_PACKET:
|
|
case RFL_ENABLE_ENCRYPTION_PACKET:
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 4,
|
|
2, &pRflPacket->uiCount,
|
|
&pRflPacket->uiCountBytes);
|
|
pRflPacket->uiNextPacketAddress =
|
|
uiFileOffset + RFL_PACKET_OVERHEAD +
|
|
6 + pRflPacket->uiCount;
|
|
break;
|
|
|
|
case RFL_CONFIG_SIZE_EVENT_PACKET:
|
|
|
|
// Get transaction ID, size threshhold, time interval, and
|
|
// size interval
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
4, &pRflPacket->uiTransID,
|
|
&pRflPacket->uiTransIDBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 4,
|
|
4, &pRflPacket->uiSizeThreshold,
|
|
&pRflPacket->uiSizeThresholdBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 8,
|
|
4, &pRflPacket->uiTimeInterval,
|
|
&pRflPacket->uiTimeIntervalBytes);
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 12,
|
|
4, &pRflPacket->uiSizeInterval,
|
|
&pRflPacket->uiSizeInterval);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
Exit:
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Positions to the next operation packet relative to the
|
|
packet that is passed in.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflGetNextOpPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
FLMBOOL * pbFoundNext
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
*pbFoundNext = FALSE;
|
|
for (;;)
|
|
{
|
|
// Stop when we either don't have a valid packet, or it is an
|
|
// operation packet.
|
|
|
|
if (!pRflPacket->bValidPacketType ||
|
|
(pRflPacket->uiPacketType != RFL_CHANGE_FIELDS_PACKET &&
|
|
pRflPacket->uiPacketType != RFL_DATA_RECORD_PACKET &&
|
|
pRflPacket->uiPacketType != RFL_ENC_DATA_RECORD_PACKET &&
|
|
pRflPacket->uiPacketType != RFL_DATA_RECORD_PACKET_VER_3))
|
|
{
|
|
*pbFoundNext = TRUE;
|
|
break;
|
|
}
|
|
|
|
// If there is no next packet, we need to break out of this loop
|
|
// and search backwards.
|
|
|
|
if (!pRflPacket->uiNextPacketAddress)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Get the next packet.
|
|
|
|
if (RC_BAD( rc = rflRetrievePacket( pRflPacket->uiFileOffset,
|
|
pRflPacket->uiNextPacketAddress,
|
|
pRflPacket)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
Exit:
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Retrieves the next operation in the RFL file and formats
|
|
it into GEDCOM for display in the viewer.
|
|
*********************************************************************/
|
|
RCODE RflGetNextNode(
|
|
NODE * pCurrOpNode,
|
|
FLMBOOL bOperationsOnly,
|
|
F_Pool * pPool,
|
|
NODE ** ppNextNodeRV,
|
|
FLMBOOL bStopAtEOF
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
NODE * pPacketNode = NULL;
|
|
void * pvMark = pPool->poolMark();
|
|
RFL_PACKET * pRflPacket;
|
|
FLMUINT uiNextPacketAddr;
|
|
FLMUINT uiPrevPacketAddr;
|
|
|
|
if (!pCurrOpNode)
|
|
{
|
|
uiNextPacketAddr = 512;
|
|
uiPrevPacketAddr = 0;
|
|
}
|
|
else
|
|
{
|
|
|
|
// If there is no next packet, return NULL.
|
|
|
|
pRflPacket = (RFL_PACKET *)GedValPtr( pCurrOpNode);
|
|
uiNextPacketAddr = pRflPacket->uiNextPacketAddress;
|
|
if (!uiNextPacketAddr)
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiPrevPacketAddr = pRflPacket->uiFileOffset;
|
|
}
|
|
if (bStopAtEOF && (FLMUINT64)uiNextPacketAddr > gv_ui64RflEof)
|
|
{
|
|
// pPacketNode should be NULL at this point.
|
|
goto Exit; // Should return FERR_OK;
|
|
}
|
|
|
|
// Create the packet node.
|
|
|
|
if ((pPacketNode = GedNodeCreate( pPool, RFL_PACKET_FIELD,
|
|
0, &rc)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
if ((pRflPacket = (RFL_PACKET *)GedAllocSpace( pPool, pPacketNode,
|
|
FLM_BINARY_TYPE, sizeof( RFL_PACKET))) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = rflRetrievePacket( uiPrevPacketAddr,
|
|
uiNextPacketAddr, pRflPacket)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If the request is for an operation, get the next operation packet.
|
|
|
|
if (bOperationsOnly)
|
|
{
|
|
FLMBOOL bFoundNext;
|
|
|
|
if (RC_BAD( rc = rflGetNextOpPacket( pRflPacket, &bFoundNext)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If there is no next packet, we don't want to return anything.
|
|
|
|
if (!bFoundNext)
|
|
{
|
|
pPacketNode = NULL;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (RC_BAD( rc) || !pPacketNode)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppNextNodeRV = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppNextNodeRV = pPacketNode;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Positions to the previous operation packet relative to the
|
|
packet that was passed in.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflGetPrevOpPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
FLMBOOL * pbFoundPrev
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
FLMBOOL bValidStartOffset;
|
|
FLMUINT uiPrevPacketAddress;
|
|
|
|
*pbFoundPrev = FALSE;
|
|
for (;;)
|
|
{
|
|
|
|
// Stop when we either don't have a valid packet, or it is an
|
|
// operation packet.
|
|
|
|
if (!pRflPacket->bValidPacketType ||
|
|
(pRflPacket->uiPacketType != RFL_CHANGE_FIELDS_PACKET &&
|
|
pRflPacket->uiPacketType != RFL_DATA_RECORD_PACKET &&
|
|
pRflPacket->uiPacketType != RFL_ENC_DATA_RECORD_PACKET &&
|
|
pRflPacket->uiPacketType != RFL_DATA_RECORD_PACKET_VER_3))
|
|
{
|
|
*pbFoundPrev = TRUE;
|
|
break;
|
|
}
|
|
|
|
bValidStartOffset = (FLMBOOL)(((pRflPacket->uiPacketAddressBytes == 4) &&
|
|
(pRflPacket->uiPacketAddress ==
|
|
pRflPacket->uiFileOffset))
|
|
? (FLMBOOL)TRUE
|
|
: (FLMBOOL)FALSE);
|
|
uiPrevPacketAddress = rflFindPrevPacket( pRflPacket->uiFileOffset, FALSE,
|
|
bValidStartOffset);
|
|
|
|
// If there is no previous packet, we are done.
|
|
|
|
if (!uiPrevPacketAddress)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Get the previous packet.
|
|
|
|
if (RC_BAD( rc = rflRetrievePacket( 0, uiPrevPacketAddress,
|
|
pRflPacket)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
Exit:
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Retrieves the previous operation in the RFL file and formats
|
|
it into GEDCOM for display in the viewer.
|
|
*********************************************************************/
|
|
RCODE RflGetPrevNode(
|
|
NODE * pCurrOpNode,
|
|
FLMBOOL bOperationsOnly,
|
|
F_Pool * pPool,
|
|
NODE ** ppNextNodeRV
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
NODE * pPacketNode = NULL;
|
|
void * pvMark = pPool->poolMark();
|
|
RFL_PACKET * pRflPacket;
|
|
FLMUINT64 ui64PrevPacketAddress;
|
|
FLMBOOL bValidStartOffset;
|
|
FLMBOOL bPositioningToEOF = FALSE;
|
|
|
|
// If pCurrOpNode is NULL, position to the last packet in the file
|
|
|
|
if (!pCurrOpNode)
|
|
{
|
|
if (RC_BAD( rc = gv_pRflFileHdl->size( &ui64PrevPacketAddress)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
ui64PrevPacketAddress = (FLMUINT64)rflFindPrevPacket( (FLMUINT)ui64PrevPacketAddress,
|
|
TRUE, FALSE);
|
|
bPositioningToEOF = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pRflPacket = (RFL_PACKET *)GedValPtr( pCurrOpNode);
|
|
|
|
// If there is no previous packet pointer, read backwards to find it.
|
|
|
|
if ((ui64PrevPacketAddress = (FLMUINT64)pRflPacket->uiPrevPacketAddress) == 0)
|
|
{
|
|
bValidStartOffset = (FLMBOOL)(((pRflPacket->uiPacketAddressBytes == 4) &&
|
|
(pRflPacket->uiPacketAddress ==
|
|
pRflPacket->uiFileOffset))
|
|
? (FLMBOOL)TRUE
|
|
: (FLMBOOL)FALSE);
|
|
|
|
ui64PrevPacketAddress = (FLMUINT64)rflFindPrevPacket( pRflPacket->uiFileOffset,
|
|
FALSE, bValidStartOffset);
|
|
}
|
|
}
|
|
|
|
if (!ui64PrevPacketAddress)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Create the packet node.
|
|
|
|
if ((pPacketNode = GedNodeCreate( pPool, RFL_PACKET_FIELD,
|
|
0, &rc)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
if ((pRflPacket = (RFL_PACKET *)GedAllocSpace( pPool, pPacketNode,
|
|
FLM_BINARY_TYPE, sizeof( RFL_PACKET))) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = rflRetrievePacket( 0, (FLMUINT)ui64PrevPacketAddress,
|
|
pRflPacket)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (bPositioningToEOF)
|
|
{
|
|
gv_ui64RflEof = (FLMUINT64)pRflPacket->uiNextPacketAddress;
|
|
}
|
|
|
|
// If the request is for an operation, get the previous operation packet.
|
|
|
|
if (bOperationsOnly)
|
|
{
|
|
FLMBOOL bFoundPrev;
|
|
|
|
if (RC_BAD( rc = rflGetPrevOpPacket( pRflPacket, &bFoundPrev)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If there is no previous packet, we don't want to return anything.
|
|
|
|
if (!bFoundPrev)
|
|
{
|
|
pPacketNode = NULL;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (RC_BAD( rc) || !pPacketNode)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppNextNodeRV = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppNextNodeRV = pPacketNode;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Retrieves the node closest to the specified address. First it
|
|
searches for a node that follows the address. Otherwise,
|
|
it searches for a node prior to the address.
|
|
*********************************************************************/
|
|
RCODE RflPositionToNode(
|
|
FLMUINT uiFileOffset,
|
|
FLMBOOL bOperationsOnly,
|
|
F_Pool * pPool,
|
|
NODE ** ppNodeRV
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pPacketNode = NULL;
|
|
FLMUINT uiPacketAddr;
|
|
FLMUINT64 ui64FileSize;
|
|
FLMBOOL bFound;
|
|
RFL_PACKET * pRflPacket;
|
|
|
|
if (RC_BAD( rc = gv_pRflFileHdl->size( &ui64FileSize)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If the specified offset is beyond the current EOF,
|
|
// simply position to the last packet.
|
|
|
|
if ((FLMUINT64)uiFileOffset >= ui64FileSize)
|
|
{
|
|
rc = RflGetPrevNode( NULL, bOperationsOnly, pPool, &pPacketNode);
|
|
goto Exit;
|
|
}
|
|
|
|
// If offset <= 512, just get the first packet.
|
|
|
|
if (uiFileOffset <= 512)
|
|
{
|
|
rc = RflGetNextNode( NULL, bOperationsOnly, pPool, &pPacketNode);
|
|
goto Exit;
|
|
}
|
|
|
|
// Create the packet node.
|
|
|
|
if ((pPacketNode = GedNodeCreate( pPool, RFL_PACKET_FIELD,
|
|
0, &rc)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
if ((pRflPacket = (RFL_PACKET *)GedAllocSpace( pPool, pPacketNode,
|
|
FLM_BINARY_TYPE, sizeof( RFL_PACKET))) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
// See if we can find a valid packet that comes on or after
|
|
// the specified address.
|
|
|
|
uiPacketAddr = rflFindNextPacket( uiFileOffset, TRUE);
|
|
if (uiPacketAddr)
|
|
{
|
|
if (RC_BAD( rc = rflRetrievePacket( 0, uiPacketAddr, pRflPacket)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (bOperationsOnly)
|
|
{
|
|
if (RC_BAD( rc = rflGetNextOpPacket( pRflPacket, &bFound)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If we found a packet, we are done. Otherwise, fall
|
|
// through and try to find a previous packet.
|
|
|
|
if (bFound)
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
// At this point, we know we didn't find a packet by searching forward,
|
|
// so we will try searching backwards.
|
|
|
|
uiPacketAddr = rflFindPrevPacket( uiFileOffset, FALSE, FALSE);
|
|
if ((uiPacketAddr) && (bOperationsOnly))
|
|
{
|
|
if (RC_BAD( rc = rflRetrievePacket( 0, uiPacketAddr,
|
|
pRflPacket)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (bOperationsOnly)
|
|
{
|
|
if (RC_BAD( rc = rflGetPrevOpPacket( pRflPacket, &bFound)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If we found a packet, we are done. Otherwise, fall
|
|
// through and try to find a previous packet.
|
|
|
|
if (bFound)
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
// At this point, we know we didn't find a packet in either direction
|
|
// by looking at only one packet worth of data, so just return
|
|
// the unknown packet at the address that was passed in.
|
|
|
|
if (RC_BAD( rc = rflRetrievePacket( 0, uiFileOffset, pRflPacket)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
if (RC_BAD( rc) || !pPacketNode)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppNodeRV = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppNodeRV = pPacketNode;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Puts a number in as the last child of the parent node.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflPutNum(
|
|
F_Pool * pPool,
|
|
NODE * pLinkToNode,
|
|
FLMBOOL bPutAsSib,
|
|
eDispTag eDispTag,
|
|
FLMUINT uiNum,
|
|
FLMUINT uiOffset,
|
|
FLMUINT uiNumExpectedBytes,
|
|
FLMUINT uiNumBytes,
|
|
NODE ** ppNode
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
NODE * pNode = NULL;
|
|
NODE * pNode2;
|
|
|
|
if (uiNumBytes)
|
|
{
|
|
|
|
// Create the number node.
|
|
|
|
if ((pNode = GedNodeCreate( pPool, makeTagNum( eDispTag), uiOffset, &rc)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Put the value into the node just created.
|
|
|
|
if (RC_BAD( rc = GedPutUINT( pPool, pNode, uiNum)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Graft the node in as the parent's last child.
|
|
|
|
if (pLinkToNode)
|
|
{
|
|
if (bPutAsSib)
|
|
{
|
|
GedSibGraft( pLinkToNode, pNode, GED_LAST);
|
|
}
|
|
else
|
|
{
|
|
GedChildGraft( pLinkToNode, pNode, GED_LAST);
|
|
}
|
|
}
|
|
|
|
if (uiNumBytes != uiNumExpectedBytes)
|
|
{
|
|
|
|
// Create the number of bytes valid node.
|
|
|
|
if ((pNode2 = GedNodeCreate( pPool,
|
|
makeTagNum( RFL_NUM_BYTES_VALID_FIELD),
|
|
0, &rc)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Put the value into the node just created.
|
|
|
|
if (RC_BAD( rc = GedPutUINT( pPool, pNode2, uiNumBytes)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Graft the node in as child to the child
|
|
|
|
GedChildGraft( pNode, pNode2, GED_LAST);
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (ppNode)
|
|
{
|
|
*ppNode = pNode;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expands a packet header into multiple GEDCOM nodes for
|
|
display.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandPacketHdr(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppParent
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
eDispTag eTagNum;
|
|
NODE * pParent;
|
|
FLMUINT uiOffset;
|
|
NODE * pNode;
|
|
|
|
if (!pRflPacket->bValidPacketType)
|
|
{
|
|
eTagNum = RFL_UNKNOWN_PACKET_FIELD;
|
|
}
|
|
else
|
|
{
|
|
switch (pRflPacket->uiPacketType)
|
|
{
|
|
case RFL_TRNS_BEGIN_PACKET:
|
|
eTagNum = RFL_TRNS_BEGIN_FIELD;
|
|
break;
|
|
case RFL_TRNS_BEGIN_EX_PACKET:
|
|
eTagNum = RFL_TRNS_BEGIN_EX_FIELD;
|
|
break;
|
|
case RFL_TRNS_COMMIT_PACKET:
|
|
eTagNum = RFL_TRNS_COMMIT_FIELD;
|
|
break;
|
|
case RFL_TRNS_ABORT_PACKET:
|
|
eTagNum = RFL_TRNS_ABORT_FIELD;
|
|
break;
|
|
case RFL_ADD_RECORD_PACKET:
|
|
case RFL_ADD_RECORD_PACKET_VER_2:
|
|
eTagNum = RFL_RECORD_ADD_FIELD;
|
|
break;
|
|
case RFL_MODIFY_RECORD_PACKET:
|
|
case RFL_MODIFY_RECORD_PACKET_VER_2:
|
|
eTagNum = RFL_RECORD_MODIFY_FIELD;
|
|
break;
|
|
case RFL_DELETE_RECORD_PACKET:
|
|
case RFL_DELETE_RECORD_PACKET_VER_2:
|
|
eTagNum = RFL_RECORD_DELETE_FIELD;
|
|
break;
|
|
case RFL_RESERVE_DRN_PACKET:
|
|
eTagNum = RFL_RESERVE_DRN_FIELD;
|
|
break;
|
|
case RFL_CHANGE_FIELDS_PACKET:
|
|
eTagNum = RFL_CHANGE_FIELDS_FIELD;
|
|
break;
|
|
case RFL_DATA_RECORD_PACKET:
|
|
eTagNum = RFL_DATA_RECORD_FIELD;
|
|
break;
|
|
case RFL_ENC_DATA_RECORD_PACKET:
|
|
eTagNum = RFL_ENC_DATA_RECORD_FIELD;
|
|
break;
|
|
case RFL_DATA_RECORD_PACKET_VER_3:
|
|
eTagNum = RFL_DATA_RECORD3_FIELD;
|
|
break;
|
|
case RFL_INDEX_SET_PACKET:
|
|
eTagNum = RFL_INDEX_SET_FIELD;
|
|
break;
|
|
case RFL_INDEX_SET_PACKET_VER_2:
|
|
eTagNum = RFL_INDEX_SET2_FIELD;
|
|
break;
|
|
case RFL_BLK_CHAIN_FREE_PACKET:
|
|
eTagNum = RFL_BLK_CHAIN_FREE_FIELD;
|
|
break;
|
|
case RFL_START_UNKNOWN_PACKET:
|
|
eTagNum = RFL_START_UNKNOWN_FIELD;
|
|
break;
|
|
case RFL_UNKNOWN_PACKET:
|
|
eTagNum = RFL_UNKNOWN_USER_PACKET_FIELD;
|
|
break;
|
|
case RFL_REDUCE_PACKET:
|
|
eTagNum = RFL_REDUCE_PACKET_FIELD;
|
|
break;
|
|
case RFL_UPGRADE_PACKET:
|
|
eTagNum = RFL_UPGRADE_PACKET_FIELD;
|
|
break;
|
|
case RFL_INDEX_SUSPEND_PACKET:
|
|
eTagNum = RFL_INDEX_SUSPEND_FIELD;
|
|
break;
|
|
case RFL_INDEX_RESUME_PACKET:
|
|
eTagNum = RFL_INDEX_RESUME_FIELD;
|
|
break;
|
|
case RFL_WRAP_KEY_PACKET:
|
|
eTagNum = RFL_WRAP_KEY_FIELD;
|
|
break;
|
|
case RFL_ENABLE_ENCRYPTION_PACKET:
|
|
eTagNum = RFL_ENABLE_ENCRYPTION_FIELD;
|
|
break;
|
|
case RFL_CONFIG_SIZE_EVENT_PACKET:
|
|
eTagNum = RFL_CONFIG_SIZE_EVENT_FIELD;
|
|
break;
|
|
default:
|
|
eTagNum = RFL_UNKNOWN_PACKET_FIELD;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Create the packet node.
|
|
|
|
if ((pParent = GedNodeCreate( pPool, makeTagNum( eTagNum),
|
|
pRflPacket->uiFileOffset, &rc)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If packet type is unknown, put it into the data portion of the
|
|
// field - if we have it.
|
|
|
|
if ((eTagNum == RFL_UNKNOWN_PACKET_FIELD) &&
|
|
(pRflPacket->bHavePacketType))
|
|
{
|
|
if (RC_BAD( rc = GedPutUINT( pPool, pParent,
|
|
pRflPacket->uiPacketType)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Add other fields from the packet header.
|
|
|
|
// Output the packet address
|
|
|
|
uiOffset = pRflPacket->uiFileOffset;
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_PACKET_ADDRESS_FIELD,
|
|
pRflPacket->uiPacketAddress,
|
|
uiOffset + RFL_PACKET_ADDRESS_OFFSET, 4,
|
|
pRflPacket->uiPacketAddressBytes, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Output the checksum.
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_PACKET_CHECKSUM_FIELD,
|
|
pRflPacket->uiPacketChecksum,
|
|
uiOffset + RFL_PACKET_CHECKSUM_OFFSET, 1,
|
|
(FLMUINT)((pRflPacket->bHavePacketChecksum)
|
|
? (FLMUINT)1
|
|
: (FLMUINT)0), &pNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if ((pRflPacket->bHavePacketChecksum) &&
|
|
(!pRflPacket->bValidChecksum))
|
|
{
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_PACKET_CHECKSUM_VALID_FIELD, 0, 0, 1, 1,
|
|
NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_PACKET_BODY_LENGTH_FIELD,
|
|
pRflPacket->uiPacketBodyLength,
|
|
uiOffset + RFL_PACKET_BODY_LENGTH_OFFSET, 2,
|
|
pRflPacket->uiPacketBodyLengthBytes, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_NEXT_PACKET_ADDRESS_FIELD,
|
|
pRflPacket->uiNextPacketAddress,
|
|
0, 4, 4, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_PREV_PACKET_ADDRESS_FIELD,
|
|
pRflPacket->uiPrevPacketAddress,
|
|
0, 4, 4, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
Exit:
|
|
*ppParent = pParent;
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expands a transaction packet into multiple GEDCOM nodes
|
|
for display of all of the subcomponents.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandTrnsPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pParent = NULL;
|
|
NODE * pLastNode;
|
|
FLMUINT uiOffset;
|
|
|
|
// Output generic packet header information.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool, &pParent)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Output transaction ID
|
|
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_TRANS_ID_FIELD,
|
|
pRflPacket->uiTransID, uiOffset,
|
|
4, pRflPacket->uiTransIDBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if( pRflPacket->uiPacketType == RFL_TRNS_BEGIN_PACKET ||
|
|
pRflPacket->uiPacketType == RFL_TRNS_BEGIN_EX_PACKET)
|
|
{
|
|
|
|
// Output the start seconds
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_START_SECONDS_FIELD,
|
|
pRflPacket->uiStartSeconds,
|
|
uiOffset,
|
|
4, pRflPacket->uiStartSecondsBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if (pRflPacket->uiPacketType == RFL_TRNS_BEGIN_EX_PACKET)
|
|
{
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_LAST_COMMITTED_TRANS_ID_FIELD,
|
|
pRflPacket->uiLastCommittedTransID,
|
|
uiOffset,
|
|
4, pRflPacket->uiLastCommittedTransIDBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
}
|
|
|
|
// Output the start microseconds, if present
|
|
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_START_MSEC_FIELD,
|
|
pRflPacket->uiStartMicro, uiOffset,
|
|
4, pRflPacket->uiStartMicroBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_START_TRNS_ADDR_FIELD,
|
|
pRflPacket->uiTransStartAddr,
|
|
uiOffset,
|
|
4, pRflPacket->uiTransStartAddrBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
|
|
// Output the start seconds & microseconds as
|
|
// an END time - because it represents the time
|
|
// the transaction ended.
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_END_SECONDS_FIELD,
|
|
pRflPacket->uiStartSeconds,
|
|
uiOffset,
|
|
4, pRflPacket->uiStartSecondsBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_END_MSEC_FIELD,
|
|
pRflPacket->uiStartMicro,
|
|
uiOffset,
|
|
4, pRflPacket->uiStartMicroBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
}
|
|
}
|
|
Exit:
|
|
if (RC_BAD( rc) || !pParent)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppForest = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppForest = pParent;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expands a start unknown packet into multiple GEDCOM nodes
|
|
for display of all of the subcomponents.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandStartUnknownPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pParent = NULL;
|
|
NODE * pLastNode;
|
|
FLMUINT uiOffset;
|
|
|
|
// Output generic packet header information.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool, &pParent)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Output transaction ID
|
|
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_TRANS_ID_FIELD,
|
|
pRflPacket->uiTransID, uiOffset,
|
|
4, pRflPacket->uiTransIDBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
Exit:
|
|
if (RC_BAD( rc) || !pParent)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppForest = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppForest = pParent;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expands an index set packet into multiple GEDCOM nodes
|
|
for display of all of the subcomponents.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandIndexSetPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pParent = NULL;
|
|
NODE * pLastNode;
|
|
FLMUINT uiOffset;
|
|
|
|
// Output generic packet header information.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool, &pParent)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Output transaction ID
|
|
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_TRANS_ID_FIELD,
|
|
pRflPacket->uiTransID, uiOffset,
|
|
4, pRflPacket->uiTransIDBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if (pRflPacket->uiPacketType == RFL_INDEX_SET_PACKET_VER_2)
|
|
{
|
|
|
|
// Output container number
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_CONTAINER_FIELD,
|
|
pRflPacket->uiContainer, uiOffset,
|
|
2, pRflPacket->uiContainerBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 2;
|
|
}
|
|
|
|
// Output index number
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_INDEX_NUM_FIELD,
|
|
pRflPacket->uiIndex, uiOffset,
|
|
2, pRflPacket->uiIndexBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 2;
|
|
|
|
// Output start DRN
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_START_DRN_FIELD,
|
|
pRflPacket->uiDrn, uiOffset,
|
|
4, pRflPacket->uiDrnBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output end DRN
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_END_DRN_FIELD,
|
|
pRflPacket->uiEndDrn, uiOffset,
|
|
4, pRflPacket->uiEndDrnBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
|
|
// Output the start time and microseconds
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_START_SECONDS_FIELD,
|
|
pRflPacket->uiStartSeconds,
|
|
uiOffset,
|
|
4, pRflPacket->uiStartSecondsBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_START_MSEC_FIELD,
|
|
pRflPacket->uiStartMicro,
|
|
uiOffset,
|
|
4, pRflPacket->uiStartMicroBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output the end time and microseconds
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_END_SECONDS_FIELD,
|
|
pRflPacket->uiEndSeconds,
|
|
uiOffset,
|
|
4, pRflPacket->uiEndSecondsBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_END_MSEC_FIELD,
|
|
pRflPacket->uiEndMicro,
|
|
uiOffset,
|
|
4, pRflPacket->uiEndMicroBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
}
|
|
Exit:
|
|
if (RC_BAD( rc) || !pParent)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppForest = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppForest = pParent;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expands a block chain free packet for display of all
|
|
of the subcomponents.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandBlkChainFreePacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pParent = NULL;
|
|
NODE * pLastNode;
|
|
FLMUINT uiOffset;
|
|
|
|
// Output generic packet header information.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool, &pParent)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Output transaction ID
|
|
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_TRANS_ID_FIELD,
|
|
pRflPacket->uiTransID, uiOffset,
|
|
4, pRflPacket->uiTransIDBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output the tracker record number
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_TRACKER_REC_FIELD,
|
|
pRflPacket->uiDrn, uiOffset,
|
|
4, pRflPacket->uiDrnBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output the block count
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_BLOCK_COUNT_FIELD,
|
|
pRflPacket->uiCount, uiOffset,
|
|
4, pRflPacket->uiCountBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output end block address
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_END_BLK_ADDR_FIELD,
|
|
pRflPacket->uiEndDrn, uiOffset,
|
|
4, pRflPacket->uiEndDrnBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
|
|
// Output the start time and microseconds
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_START_SECONDS_FIELD,
|
|
pRflPacket->uiStartSeconds,
|
|
uiOffset,
|
|
4, pRflPacket->uiStartSecondsBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_START_MSEC_FIELD,
|
|
pRflPacket->uiStartMicro,
|
|
uiOffset,
|
|
4, pRflPacket->uiStartMicroBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output the end time and microseconds
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_END_SECONDS_FIELD,
|
|
pRflPacket->uiEndSeconds,
|
|
uiOffset,
|
|
4, pRflPacket->uiEndSecondsBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_END_MSEC_FIELD,
|
|
pRflPacket->uiEndMicro,
|
|
uiOffset,
|
|
4, pRflPacket->uiEndMicroBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (RC_BAD( rc) || !pParent)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppForest = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppForest = pParent;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expands a reduce packet into multiple GEDCOM nodes
|
|
for display of all of the subcomponents.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandReducePacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pParent = NULL;
|
|
NODE * pLastNode;
|
|
FLMUINT uiOffset;
|
|
|
|
// Output generic packet header information.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool, &pParent)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Output transaction ID
|
|
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_TRANS_ID_FIELD,
|
|
pRflPacket->uiTransID, uiOffset,
|
|
4, pRflPacket->uiTransIDBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output the count
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_BLOCK_COUNT_FIELD,
|
|
pRflPacket->uiEndDrn, uiOffset,
|
|
4, pRflPacket->uiEndDrnBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
Exit:
|
|
|
|
if (RC_BAD( rc) || !pParent)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppForest = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppForest = pParent;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expands an upgrade packet into multiple GEDCOM nodes
|
|
for display of all of the subcomponents.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandUpgradePacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pParent = NULL;
|
|
NODE * pLastNode;
|
|
FLMUINT uiOffset;
|
|
|
|
// Output generic packet header information.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool, &pParent)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Output transaction ID
|
|
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_TRANS_ID_FIELD,
|
|
pRflPacket->uiTransID, uiOffset,
|
|
4, pRflPacket->uiTransIDBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output old DB version
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_OLD_DB_VERSION_FIELD,
|
|
pRflPacket->uiDrn, uiOffset,
|
|
4, pRflPacket->uiDrnBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output new DB version
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_NEW_DB_VERSION_FIELD,
|
|
pRflPacket->uiEndDrn, uiOffset,
|
|
4, pRflPacket->uiEndDrnBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
Exit:
|
|
|
|
if (RC_BAD( rc) || !pParent)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppForest = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppForest = pParent;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expands an index suspend or resume packet
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandIndexStatePacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pParent = NULL;
|
|
NODE * pLastNode;
|
|
FLMUINT uiOffset;
|
|
|
|
// Output generic packet header information.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool, &pParent)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Output transaction ID
|
|
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_TRANS_ID_FIELD,
|
|
pRflPacket->uiTransID, uiOffset,
|
|
4, pRflPacket->uiTransIDBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output old DB version
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_INDEX_NUM_FIELD,
|
|
pRflPacket->uiIndex, uiOffset,
|
|
2, pRflPacket->uiIndexBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
Exit:
|
|
|
|
if (RC_BAD( rc) || !pParent)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppForest = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppForest = pParent;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expand a data record packet.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandDataPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
FLMBOOL bOutputPacket,
|
|
FLMUINT uiPacketType,
|
|
NODE ** ppDataPacketNode,
|
|
FLMUINT * puiDataLen,
|
|
FLMUINT * puiLevel
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pDataPacketNode = NULL;
|
|
FLMBYTE * pucPacketBody;
|
|
FLMUINT uiBytesRead;
|
|
FLMUINT uiOffset;
|
|
FLMUINT uiTagNum;
|
|
FLMUINT uiTagNumLen;
|
|
FLMUINT uiDataType;
|
|
FLMUINT uiDataTypeLen;
|
|
FLMUINT uiLevel;
|
|
FLMUINT uiLevelLen;
|
|
FLMUINT uiDataLen;
|
|
FLMUINT uiDataLenLen;
|
|
NODE * pTmpNode;
|
|
FLMUINT uiLastLevel = 0;
|
|
NODE * pLastNode;
|
|
FLMBYTE * pucNodeData;
|
|
FLMUINT uiNodeDataLen;
|
|
FLMUINT uiEncrypted;
|
|
FLMUINT uiEncryptedLen;
|
|
FLMUINT uiEncLen;
|
|
FLMUINT uiEncLenLen;
|
|
FLMUINT uiEncDefID;
|
|
FLMUINT uiEncDefIDLen;
|
|
NODE * pDataNode;
|
|
NODE * pTagNode;
|
|
NODE * pRootNode = NULL;
|
|
|
|
// Output the packet header.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool,
|
|
&pDataPacketNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If there is no packet body, we are done.
|
|
|
|
if (!pRflPacket->uiPacketBodyLength)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Read the packet body from disk.
|
|
|
|
pucPacketBody = &gv_rflBuffer [0];
|
|
f_memset( pucPacketBody, 0, pRflPacket->uiPacketBodyLength);
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
rc = gv_pRflFileHdl->read( uiOffset,
|
|
pRflPacket->uiPacketBodyLength,
|
|
pucPacketBody,
|
|
&uiBytesRead);
|
|
if (RC_BAD( rc))
|
|
{
|
|
if (rc != FERR_IO_END_OF_FILE || !uiBytesRead)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
goto Exit;
|
|
}
|
|
}
|
|
if (!uiBytesRead)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pLastNode = pDataPacketNode;
|
|
while (pLastNode->next)
|
|
{
|
|
pLastNode = pLastNode->next;
|
|
}
|
|
|
|
// Go through the packet body and create GEDCOM nodes.
|
|
|
|
while (uiBytesRead)
|
|
{
|
|
if (*puiDataLen)
|
|
{
|
|
|
|
uiDataLen = *puiDataLen;
|
|
uiDataType = FLM_BINARY_TYPE;
|
|
uiLastLevel = 0;
|
|
uiLevel = *puiLevel;
|
|
|
|
// Create the necessary number of dummy parent nodes.
|
|
|
|
if (uiLastLevel < uiLevel)
|
|
{
|
|
for (;;)
|
|
{
|
|
if ((pTmpNode = GedNodeCreate( pPool,
|
|
makeTagNum( RFL_MORE_DATA_FIELD), 0, &rc)) == 0)
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (!pRootNode)
|
|
{
|
|
GedSibGraft( pLastNode, pTmpNode, GED_LAST);
|
|
pRootNode = pTmpNode;
|
|
}
|
|
else
|
|
{
|
|
GedChildGraft( pLastNode, pTmpNode, GED_LAST);
|
|
}
|
|
pLastNode = pTmpNode;
|
|
if (uiLastLevel + 1 == uiLevel)
|
|
break;
|
|
uiLastLevel++;
|
|
}
|
|
}
|
|
|
|
// Create a GEDCOM node.
|
|
|
|
if ((pTagNode = GedNodeCreate( pPool, makeTagNum( RFL_MORE_DATA_FIELD),
|
|
uiOffset, &rc)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
pDataNode = pTagNode;
|
|
}
|
|
|
|
// Remaining length better be at least two or we
|
|
// have an incomplete packet - we need to at least
|
|
// be able to get the tag number at this point.
|
|
|
|
else if (uiBytesRead < 2)
|
|
{
|
|
if (RC_BAD( rc = rflPutNum( pPool, NULL, TRUE,
|
|
RFL_TAG_NUM_FIELD,
|
|
(FLMUINT)(*pucPacketBody), uiOffset,
|
|
2, 1, &pTagNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pDataNode = NULL;
|
|
|
|
// Reset the context in case there is another packet
|
|
// following this one.
|
|
|
|
uiLevel = uiLastLevel;
|
|
*puiDataLen = uiDataLen = 0;
|
|
uiBytesRead = 0;
|
|
}
|
|
else if (uiBytesRead == 2)
|
|
{
|
|
if ((uiTagNum = (FLMUINT)FB2UW( pucPacketBody)) != 0)
|
|
{
|
|
if (RC_BAD( rc = rflPutNum( pPool, NULL, TRUE,
|
|
RFL_TAG_NUM_FIELD,
|
|
uiTagNum, uiOffset,
|
|
2, 2, &pTagNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
pDataNode = NULL;
|
|
*puiDataLen = uiDataLen = 0;
|
|
uiLevel = uiLastLevel;
|
|
uiBytesRead = 0;
|
|
}
|
|
else
|
|
{
|
|
|
|
// Reset the context in case there is another packet
|
|
// following this one.
|
|
|
|
*puiDataLen = uiDataLen = 0;
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FLMBOOL bIncompleteHdr = FALSE;
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, 2, &uiTagNum, &uiTagNumLen);
|
|
pucPacketBody += uiTagNumLen;
|
|
uiBytesRead -= uiTagNumLen;
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, 1, &uiDataType, &uiDataTypeLen);
|
|
pucPacketBody += uiDataTypeLen;
|
|
uiBytesRead -= uiDataTypeLen;
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, 1, &uiLevel, &uiLevelLen);
|
|
pucPacketBody += uiLevelLen;
|
|
uiBytesRead -= uiLevelLen;
|
|
|
|
if (uiPacketType == RFL_DATA_RECORD_PACKET_VER_3)
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, 4, &uiDataLen, &uiDataLenLen);
|
|
if (uiDataLenLen < 4)
|
|
{
|
|
bIncompleteHdr = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, 2, &uiDataLen, &uiDataLenLen);
|
|
if (uiDataLenLen < 2)
|
|
{
|
|
bIncompleteHdr = TRUE;
|
|
}
|
|
}
|
|
pucPacketBody += uiDataLenLen;
|
|
uiBytesRead -= uiDataLenLen;
|
|
|
|
|
|
// If we have an encrypted packet, handle the remaining fields here
|
|
|
|
uiEncrypted = 0;
|
|
uiEncryptedLen = 0;
|
|
uiEncDefID = 0;
|
|
uiEncDefIDLen = 0;
|
|
uiEncLen = 0;
|
|
uiEncLenLen = 0;
|
|
if (uiPacketType == RFL_ENC_DATA_RECORD_PACKET ||
|
|
uiPacketType == RFL_DATA_RECORD_PACKET_VER_3)
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, 1, &uiEncrypted, &uiEncryptedLen);
|
|
pucPacketBody += uiEncryptedLen;
|
|
uiBytesRead -= uiEncryptedLen;
|
|
|
|
if (!uiEncryptedLen)
|
|
{
|
|
bIncompleteHdr = TRUE;
|
|
}
|
|
else if (uiEncrypted)
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, 2, &uiEncDefID, &uiEncDefIDLen);
|
|
pucPacketBody += uiEncDefIDLen;
|
|
uiBytesRead -= uiEncDefIDLen;
|
|
|
|
if (uiPacketType == RFL_DATA_RECORD_PACKET_VER_3)
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, 4, &uiEncLen, &uiEncLenLen);
|
|
if (uiEncLenLen < 4)
|
|
{
|
|
bIncompleteHdr = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, 2, &uiEncLen, &uiEncLenLen);
|
|
if (uiEncLenLen < 2)
|
|
{
|
|
bIncompleteHdr = TRUE;
|
|
}
|
|
}
|
|
pucPacketBody += uiEncLenLen;
|
|
uiBytesRead -= uiEncLenLen;
|
|
}
|
|
}
|
|
|
|
// If we have incomplete or bad header information,
|
|
// output each piece of header info individually, subordinate
|
|
// to a "tag number" field. Then output the
|
|
// data there too.
|
|
|
|
if (bIncompleteHdr || !uiTagNum ||
|
|
(uiDataType != FLM_TEXT_TYPE &&
|
|
uiDataType != FLM_NUMBER_TYPE &&
|
|
uiDataType != FLM_BINARY_TYPE &&
|
|
uiDataType != FLM_CONTEXT_TYPE &&
|
|
uiDataType != FLM_BLOB_TYPE) ||
|
|
(!pRootNode && uiLevel) ||
|
|
(pRootNode && uiLevel > uiLastLevel + 1))
|
|
{
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, NULL, TRUE, RFL_TAG_NUM_FIELD,
|
|
uiTagNum, uiOffset, 2, uiTagNumLen, &pTagNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiTagNumLen;
|
|
|
|
if ( RC_BAD( rc = rflPutNum( pPool, pTagNode, FALSE, RFL_TYPE_FIELD,
|
|
uiDataType, uiOffset, 1, uiDataTypeLen, &pTmpNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiDataTypeLen;
|
|
|
|
if ( RC_BAD( rc = rflPutNum( pPool, pTmpNode, TRUE, RFL_LEVEL_FIELD,
|
|
uiLevel, uiOffset, 1, uiLevelLen, &pTmpNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiLevelLen;
|
|
|
|
if (uiPacketType == RFL_DATA_RECORD_PACKET_VER_3)
|
|
{
|
|
if ( RC_BAD( rc = rflPutNum( pPool, pTmpNode, TRUE, RFL_DATA_LEN_FIELD,
|
|
uiDataLen, uiOffset, 4, uiDataLenLen, &pTmpNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( RC_BAD( rc = rflPutNum( pPool, pTmpNode, TRUE, RFL_DATA_LEN_FIELD,
|
|
uiDataLen, uiOffset, 2, uiDataLenLen, &pTmpNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
uiOffset += uiDataLenLen;
|
|
|
|
if (uiPacketType == RFL_ENC_DATA_RECORD_PACKET ||
|
|
uiPacketType == RFL_DATA_RECORD_PACKET_VER_3)
|
|
{
|
|
if ( RC_BAD( rc = rflPutNum( pPool, pTmpNode, TRUE, RFL_ENC_FIELD,
|
|
uiEncrypted, uiOffset, 1, uiEncryptedLen, &pTmpNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiEncryptedLen;
|
|
|
|
if (uiEncryptedLen && uiEncrypted)
|
|
{
|
|
if ( RC_BAD( rc = rflPutNum( pPool, pTmpNode, TRUE, RFL_ENC_DEF_ID_FIELD,
|
|
uiEncDefID, uiOffset, 2, uiEncDefIDLen, &pTmpNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiEncDefIDLen;
|
|
|
|
if (uiPacketType == RFL_DATA_RECORD_PACKET_VER_3)
|
|
{
|
|
if ( RC_BAD( rc = rflPutNum( pPool, pTmpNode, TRUE, RFL_ENC_DATA_LEN_FIELD,
|
|
uiEncLen, uiOffset, 4, uiEncLenLen, &pTmpNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( RC_BAD( rc = rflPutNum( pPool, pTmpNode, TRUE, RFL_ENC_DATA_LEN_FIELD,
|
|
uiEncLen, uiOffset, 2, uiEncLenLen, &pTmpNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
uiOffset += uiEncLenLen;
|
|
|
|
if (uiEncLenLen == 2)
|
|
{
|
|
uiDataLen = uiEncLen;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (uiDataLen && !bIncompleteHdr)
|
|
{
|
|
|
|
// Create a GEDCOM node for the data.
|
|
|
|
if ((pDataNode = GedNodeCreate( pPool, makeTagNum( RFL_DATA_FIELD),
|
|
uiOffset, &rc)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiDataType = FLM_BINARY_TYPE;
|
|
GedSibGraft( pTmpNode, pDataNode, GED_LAST);
|
|
}
|
|
else
|
|
{
|
|
uiDataLen = 0;
|
|
pDataNode = NULL;
|
|
}
|
|
|
|
// If we didn't get a good field, keep things at their current
|
|
// level.
|
|
|
|
uiLevel = uiLastLevel;
|
|
}
|
|
else
|
|
{
|
|
|
|
// Create a GEDCOM node.
|
|
|
|
if ((pTagNode = GedNodeCreate( pPool, uiTagNum, uiOffset, &rc)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 6;
|
|
if (uiPacketType == RFL_ENC_DATA_RECORD_PACKET)
|
|
{
|
|
uiOffset++;
|
|
if (uiEncrypted)
|
|
{
|
|
uiOffset += 4;
|
|
uiDataLen = uiEncLen;
|
|
}
|
|
}
|
|
if (uiDataLen)
|
|
{
|
|
pDataNode = pTagNode;
|
|
}
|
|
else
|
|
{
|
|
pDataNode = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Graft the tag node relative to the last node, if any.
|
|
// Otherwise, it becomes the root node.
|
|
|
|
if (!pRootNode)
|
|
{
|
|
GedSibGraft( pLastNode, pTagNode, GED_LAST);
|
|
pRootNode = pTagNode;
|
|
uiLastLevel = 0;
|
|
}
|
|
else if (uiLevel > uiLastLevel)
|
|
{
|
|
GedChildGraft( pLastNode, pTagNode, GED_LAST);
|
|
uiLastLevel = uiLevel;
|
|
}
|
|
else
|
|
{
|
|
while (uiLevel < uiLastLevel)
|
|
{
|
|
pLastNode = GedParent( pLastNode);
|
|
uiLastLevel--;
|
|
}
|
|
GedSibGraft( pLastNode, pTagNode, GED_LAST);
|
|
uiLastLevel = uiLevel;
|
|
}
|
|
pLastNode = pTagNode;
|
|
|
|
// Allocate space for the data. We call this even if uiDataLen is
|
|
// zero so that the appropriate data type will be set in the node
|
|
// as well.
|
|
|
|
if (pDataNode)
|
|
{
|
|
uiNodeDataLen = (FLMUINT)((uiDataLen <= uiBytesRead)
|
|
? uiDataLen
|
|
: uiBytesRead);
|
|
if (((pucNodeData = (FLMBYTE *)GedAllocSpace( pPool, pDataNode,
|
|
uiDataType,
|
|
uiNodeDataLen)) == NULL) &&
|
|
(uiNodeDataLen))
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
if (uiNodeDataLen)
|
|
{
|
|
f_memcpy( pucNodeData, pucPacketBody, uiNodeDataLen);
|
|
pucPacketBody += uiNodeDataLen;
|
|
uiOffset += uiNodeDataLen;
|
|
uiDataLen -= uiNodeDataLen;
|
|
uiBytesRead -= uiNodeDataLen;
|
|
}
|
|
}
|
|
|
|
*puiLevel = uiLastLevel;
|
|
if ((*puiDataLen = uiDataLen) != 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (RC_BAD( rc) || !pDataPacketNode || !bOutputPacket)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
if ((*ppDataPacketNode) && (pDataPacketNode))
|
|
{
|
|
GedSibGraft( *ppDataPacketNode, pDataPacketNode, GED_LAST);
|
|
}
|
|
if (pDataPacketNode)
|
|
{
|
|
*ppDataPacketNode = pDataPacketNode;
|
|
}
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expand a change fields packet.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandChangeFieldsPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
FLMBOOL bOutputPacket,
|
|
NODE ** ppChangeFieldsPacketNode,
|
|
FLMUINT * puiDataLen
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pChangeFieldsPacketNode = NULL;
|
|
NODE * pChangeNode;
|
|
NODE * pLastNode;
|
|
FLMBYTE * pucPacketBody;
|
|
FLMUINT uiBytesRead;
|
|
FLMUINT uiOffset;
|
|
eDispTag eChangeTagNum;
|
|
FLMUINT uiDataTagNum;
|
|
FLMUINT uiDataLen;
|
|
FLMUINT uiChangeType;
|
|
FLMBYTE * pucNodeData;
|
|
NODE * pDataNode;
|
|
FLMUINT uiNodeDataLen;
|
|
FLMUINT uiTmp;
|
|
FLMUINT uiLen;
|
|
FLMUINT uiDataLenLen;
|
|
|
|
// Output the packet header.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool,
|
|
&pChangeFieldsPacketNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If there is no packet body, we are done.
|
|
|
|
if (!pRflPacket->uiPacketBodyLength)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Read the packet body from disk.
|
|
|
|
pucPacketBody = &gv_rflBuffer [0];
|
|
f_memset( pucPacketBody, 0, pRflPacket->uiPacketBodyLength);
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
rc = gv_pRflFileHdl->read( uiOffset,
|
|
pRflPacket->uiPacketBodyLength,
|
|
pucPacketBody,
|
|
&uiBytesRead);
|
|
if (RC_BAD( rc))
|
|
{
|
|
if (rc != FERR_IO_END_OF_FILE || !uiBytesRead)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
goto Exit;
|
|
}
|
|
}
|
|
if (!uiBytesRead)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pLastNode = pChangeFieldsPacketNode;
|
|
while (pLastNode->next)
|
|
{
|
|
pLastNode = pLastNode->next;
|
|
}
|
|
|
|
// Go through the packet body and create GEDCOM nodes.
|
|
|
|
while (uiBytesRead)
|
|
{
|
|
if (*puiDataLen)
|
|
{
|
|
uiDataTagNum = RFL_MORE_DATA_FIELD;
|
|
uiDataLen = *puiDataLen;
|
|
|
|
// Create a dummy change node.
|
|
|
|
if ((pChangeNode = GedNodeCreate( pPool, makeTagNum( RFL_MORE_DATA_FIELD),
|
|
0, &rc)) == 0)
|
|
{
|
|
goto Exit;
|
|
}
|
|
GedSibGraft( pLastNode, pChangeNode, GED_LAST);
|
|
}
|
|
else
|
|
{
|
|
uiChangeType = *pucPacketBody++;
|
|
switch (uiChangeType)
|
|
{
|
|
case RFL_INSERT_FIELD:
|
|
eChangeTagNum = RFL_INSERT_FLD_FIELD;
|
|
break;
|
|
case RFL_MODIFY_FIELD:
|
|
eChangeTagNum = RFL_MODIFY_FLD_FIELD;
|
|
break;
|
|
case RFL_DELETE_FIELD:
|
|
eChangeTagNum = RFL_DELETE_FLD_FIELD;
|
|
break;
|
|
case RFL_END_FIELD_CHANGES:
|
|
eChangeTagNum = RFL_END_CHANGES_FIELD;
|
|
break;
|
|
// Added
|
|
case RFL_INSERT_ENC_FIELD:
|
|
eChangeTagNum = RFL_INSERT_ENC_FLD_FIELD;
|
|
break;
|
|
case RFL_MODIFY_ENC_FIELD:
|
|
eChangeTagNum = RFL_MODIFY_ENC_FLD_FIELD;
|
|
break;
|
|
case RFL_INSERT_LARGE_FIELD:
|
|
eChangeTagNum = RFL_INSERT_LARGE_FLD_FIELD;
|
|
break;
|
|
case RFL_INSERT_ENC_LARGE_FIELD:
|
|
eChangeTagNum = RFL_INSERT_ENC_LARGE_FLD_FIELD;
|
|
break;
|
|
case RFL_MODIFY_LARGE_FIELD:
|
|
eChangeTagNum = RFL_MODIFY_LARGE_FLD_FIELD;
|
|
break;
|
|
case RFL_MODIFY_ENC_LARGE_FIELD:
|
|
eChangeTagNum = RFL_MODIFY_ENC_LARGE_FLD_FIELD;
|
|
break;
|
|
default:
|
|
eChangeTagNum = RFL_UNKNOWN_CHANGE_TYPE_FIELD;
|
|
break;
|
|
}
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
eChangeTagNum,
|
|
uiChangeType, uiOffset,
|
|
1, 1, &pChangeNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset++;
|
|
uiBytesRead--;
|
|
|
|
// Output the position field.
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
2, &uiTmp, &uiLen);
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pChangeNode, FALSE,
|
|
RFL_POSITION_FIELD,
|
|
uiTmp, uiOffset,
|
|
2, uiLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiLen;
|
|
pucPacketBody += uiLen;
|
|
uiBytesRead -= uiLen;
|
|
|
|
uiDataLen = 0;
|
|
if (uiChangeType == RFL_INSERT_FIELD ||
|
|
uiChangeType == RFL_INSERT_ENC_FIELD ||
|
|
uiChangeType == RFL_INSERT_LARGE_FIELD ||
|
|
uiChangeType == RFL_INSERT_ENC_LARGE_FIELD)
|
|
{
|
|
|
|
// Output tag number.
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
2, &uiTmp, &uiLen);
|
|
if (RC_BAD( rc = rflPutNum( pPool, pChangeNode, FALSE,
|
|
RFL_TAG_NUM_FIELD,
|
|
uiTmp, uiOffset,
|
|
2, uiLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiLen;
|
|
pucPacketBody += uiLen;
|
|
uiBytesRead -= uiLen;
|
|
|
|
// Output data type
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
1, &uiTmp, &uiLen);
|
|
if (RC_BAD( rc = rflPutNum( pPool, pChangeNode, FALSE,
|
|
RFL_TYPE_FIELD,
|
|
uiTmp, uiOffset,
|
|
1, uiLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiLen;
|
|
pucPacketBody += uiLen;
|
|
uiBytesRead -= uiLen;
|
|
|
|
// Output level
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
1, &uiTmp, &uiLen);
|
|
if (RC_BAD( rc = rflPutNum( pPool, pChangeNode, FALSE,
|
|
RFL_LEVEL_FIELD,
|
|
uiTmp, uiOffset,
|
|
1, uiLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiLen;
|
|
pucPacketBody += uiLen;
|
|
uiBytesRead -= uiLen;
|
|
|
|
// Output data length
|
|
|
|
uiDataLenLen = (uiChangeType == RFL_INSERT_LARGE_FIELD ||
|
|
uiChangeType == RFL_INSERT_ENC_LARGE_FIELD)
|
|
? 4
|
|
: 2;
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
uiDataLenLen, &uiTmp, &uiLen);
|
|
if (RC_BAD( rc = rflPutNum( pPool, pChangeNode, FALSE,
|
|
RFL_DATA_LEN_FIELD,
|
|
uiTmp, uiOffset,
|
|
uiDataLenLen, uiLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiLen;
|
|
pucPacketBody += uiLen;
|
|
uiBytesRead -= uiLen;
|
|
if (uiLen == 2)
|
|
{
|
|
uiDataLen = uiTmp;
|
|
}
|
|
|
|
uiDataTagNum = RFL_DATA_FIELD;
|
|
if (uiChangeType == RFL_INSERT_ENC_FIELD ||
|
|
uiChangeType == RFL_INSERT_ENC_LARGE_FIELD)
|
|
{
|
|
// Output the encryption definition id
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, 2, &uiTmp, &uiLen);
|
|
if ( RC_BAD( rc = rflPutNum( pPool, pChangeNode, FALSE, RFL_ENC_DEF_ID_FIELD,
|
|
uiTmp, uiOffset, 2, uiLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiLen;
|
|
pucPacketBody += uiLen;
|
|
uiBytesRead -= uiLen;
|
|
|
|
// Output the encrypted data length
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, uiDataLenLen, &uiTmp, &uiLen);
|
|
if ( RC_BAD( rc = rflPutNum( pPool, pChangeNode, FALSE, RFL_ENC_DATA_LEN_FIELD,
|
|
uiTmp, uiOffset, uiDataLenLen, uiLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiLen;
|
|
pucPacketBody += uiLen;
|
|
uiBytesRead -= uiLen;
|
|
if (uiLen == 2)
|
|
{
|
|
uiDataLen = uiTmp;
|
|
}
|
|
}
|
|
}
|
|
else if (uiChangeType == RFL_MODIFY_FIELD ||
|
|
uiChangeType == RFL_MODIFY_ENC_FIELD ||
|
|
uiChangeType == RFL_MODIFY_LARGE_FIELD ||
|
|
uiChangeType == RFL_MODIFY_ENC_LARGE_FIELD)
|
|
{
|
|
|
|
// Output change bytes type
|
|
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
1, &uiTmp, &uiLen);
|
|
if ((uiTmp == RFL_REPLACE_BYTES) && (uiLen))
|
|
{
|
|
if (RC_BAD( rc = rflPutNum( pPool, pChangeNode, FALSE,
|
|
RFL_REPLACE_BYTES_FIELD,
|
|
uiTmp, uiOffset,
|
|
1, uiLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (RC_BAD( rc = rflPutNum( pPool, pChangeNode, FALSE,
|
|
RFL_UNKNOWN_CHANGE_BYTES_FIELD,
|
|
uiTmp, uiOffset,
|
|
1, uiLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
uiOffset += uiLen;
|
|
pucPacketBody += uiLen;
|
|
uiBytesRead -= uiLen;
|
|
|
|
// Output data length
|
|
|
|
uiDataLenLen = (uiChangeType == RFL_MODIFY_LARGE_FIELD ||
|
|
uiChangeType == RFL_MODIFY_ENC_LARGE_FIELD)
|
|
? 4
|
|
: 2;
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0,
|
|
uiDataLenLen, &uiTmp, &uiLen);
|
|
if (RC_BAD( rc = rflPutNum( pPool, pChangeNode, FALSE,
|
|
RFL_DATA_LEN_FIELD,
|
|
uiTmp, uiOffset,
|
|
uiDataLenLen, uiLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiLen;
|
|
pucPacketBody += uiLen;
|
|
uiBytesRead -= uiLen;
|
|
if (uiLen == uiDataLenLen)
|
|
{
|
|
uiDataLen = uiTmp;
|
|
}
|
|
uiDataTagNum = RFL_DATA_FIELD;
|
|
if (uiChangeType == RFL_MODIFY_ENC_FIELD ||
|
|
uiChangeType == RFL_MODIFY_ENC_LARGE_FIELD)
|
|
{
|
|
// Output the encryption definition id
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, 2, &uiTmp, &uiLen);
|
|
if ( RC_BAD( rc = rflPutNum( pPool, pChangeNode, FALSE, RFL_ENC_DEF_ID_FIELD,
|
|
uiTmp, uiOffset, 2, uiLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiLen;
|
|
pucPacketBody += uiLen;
|
|
uiBytesRead -= uiLen;
|
|
|
|
// Output the encrypted data length
|
|
rflGetNumValue( pucPacketBody, uiBytesRead, 0, uiDataLenLen, &uiTmp, &uiLen);
|
|
if ( RC_BAD( rc = rflPutNum( pPool, pChangeNode, FALSE, RFL_ENC_DATA_LEN_FIELD,
|
|
uiTmp, uiOffset, uiDataLenLen, uiLen, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += uiLen;
|
|
pucPacketBody += uiLen;
|
|
uiBytesRead -= uiLen;
|
|
if (uiLen == uiDataLenLen)
|
|
{
|
|
uiDataLen = uiTmp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create a data node, if there is data to output.
|
|
|
|
if (uiDataLen && uiBytesRead)
|
|
{
|
|
// Create a GEDCOM node.
|
|
|
|
if ((pDataNode = GedNodeCreate( pPool, uiDataTagNum,
|
|
uiOffset, &rc)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
GedChildGraft( pChangeNode, pDataNode, GED_LAST);
|
|
uiNodeDataLen = (FLMUINT)((uiDataLen <= uiBytesRead)
|
|
? uiDataLen
|
|
: uiBytesRead);
|
|
if (((pucNodeData = (FLMBYTE *)GedAllocSpace( pPool, pDataNode,
|
|
FLM_BINARY_TYPE,
|
|
uiNodeDataLen)) == NULL) &&
|
|
(uiNodeDataLen))
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
if (uiNodeDataLen)
|
|
{
|
|
f_memcpy( pucNodeData, pucPacketBody, uiNodeDataLen);
|
|
pucPacketBody += uiNodeDataLen;
|
|
uiOffset += uiNodeDataLen;
|
|
uiDataLen -= uiNodeDataLen;
|
|
uiBytesRead -= uiNodeDataLen;
|
|
}
|
|
}
|
|
|
|
pLastNode = pChangeNode;
|
|
if ((*puiDataLen = uiDataLen) != 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (RC_BAD( rc) || !pChangeFieldsPacketNode || !bOutputPacket)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
if ((*ppChangeFieldsPacketNode) && (pChangeFieldsPacketNode))
|
|
{
|
|
GedSibGraft( *ppChangeFieldsPacketNode,
|
|
pChangeFieldsPacketNode, GED_LAST);
|
|
}
|
|
if (pChangeFieldsPacketNode)
|
|
{
|
|
*ppChangeFieldsPacketNode = pChangeFieldsPacketNode;
|
|
}
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expand the change field packets for a record
|
|
modify operation into the appropriate GEDCOM nodes.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandRecordPackets(
|
|
F_Pool * pPool,
|
|
FLMUINT uiOffset,
|
|
FLMUINT uiPacketType,
|
|
NODE ** ppLastPacketNode,
|
|
FLMUINT uiPacketOffset
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
RFL_PACKET RflPacket;
|
|
FLMUINT uiDataLen = 0;
|
|
FLMUINT uiLevel = 0;
|
|
FLMBOOL bOutputPacket;
|
|
NODE * pLastPacketNode = NULL;
|
|
|
|
if( *ppLastPacketNode)
|
|
{
|
|
pLastPacketNode = *ppLastPacketNode;
|
|
}
|
|
|
|
for (;;)
|
|
{
|
|
|
|
// Quit when there are no more packets.
|
|
|
|
if (!uiOffset)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Retrieve the next packet.
|
|
|
|
if (RC_BAD( rc = rflRetrievePacket( 0, uiOffset, &RflPacket)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (uiPacketType == 0xFF)
|
|
{
|
|
if (RflPacket.uiPacketType == RFL_DATA_RECORD_PACKET ||
|
|
RflPacket.uiPacketType == RFL_ENC_DATA_RECORD_PACKET ||
|
|
RflPacket.uiPacketType == RFL_DATA_RECORD_PACKET_VER_3 ||
|
|
RflPacket.uiPacketType == RFL_CHANGE_FIELDS_PACKET)
|
|
{
|
|
uiPacketType = RflPacket.uiPacketType;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Stop when we don't have a valid data packet.
|
|
|
|
if (!RflPacket.bValidPacketType ||
|
|
RflPacket.uiPacketType != uiPacketType)
|
|
{
|
|
break;
|
|
}
|
|
|
|
bOutputPacket = (FLMBOOL)(((uiPacketOffset == 0) ||
|
|
(RflPacket.uiFileOffset >= uiPacketOffset))
|
|
? (FLMBOOL)TRUE
|
|
: (FLMBOOL)FALSE);
|
|
|
|
if (uiPacketType == RFL_DATA_RECORD_PACKET ||
|
|
uiPacketType == RFL_ENC_DATA_RECORD_PACKET ||
|
|
uiPacketType == RFL_DATA_RECORD_PACKET_VER_3)
|
|
{
|
|
if (RC_BAD( rc = rflExpandDataPacket( &RflPacket, pPool,
|
|
bOutputPacket, uiPacketType,
|
|
&pLastPacketNode, &uiDataLen, &uiLevel)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (RC_BAD( rc = rflExpandChangeFieldsPacket( &RflPacket, pPool,
|
|
bOutputPacket,
|
|
&pLastPacketNode, &uiDataLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if( !(*ppLastPacketNode))
|
|
{
|
|
*ppLastPacketNode = pLastPacketNode;
|
|
}
|
|
|
|
// If we are trying to output only a single packet, stop once we
|
|
// have output it.
|
|
|
|
if ((bOutputPacket) && (uiPacketOffset))
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Set the address for the next packet.
|
|
|
|
uiOffset = RflPacket.uiNextPacketAddress;
|
|
}
|
|
Exit:
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expands a record operation packet into multiple GEDCOM nodes
|
|
for display of all of the subcomponents.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandRecOpPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest,
|
|
FLMUINT uiPacketOffset
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pParent = NULL;
|
|
NODE * pLastNode;
|
|
FLMUINT uiOffset;
|
|
|
|
if ((!uiPacketOffset) || (uiPacketOffset == pRflPacket->uiFileOffset))
|
|
{
|
|
|
|
// Output generic packet header information.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool, &pParent)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Output transaction ID
|
|
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_TRANS_ID_FIELD,
|
|
pRflPacket->uiTransID, uiOffset,
|
|
4, pRflPacket->uiTransIDBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output the container
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_CONTAINER_FIELD,
|
|
pRflPacket->uiContainer,
|
|
uiOffset,
|
|
2, pRflPacket->uiContainerBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 2;
|
|
|
|
// Output the DRN
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_DRN_FIELD,
|
|
pRflPacket->uiDrn,
|
|
uiOffset,
|
|
4, pRflPacket->uiDrnBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output flags
|
|
|
|
if( pRflPacket->uiPacketType == RFL_ADD_RECORD_PACKET_VER_2 ||
|
|
pRflPacket->uiPacketType == RFL_MODIFY_RECORD_PACKET_VER_2 ||
|
|
pRflPacket->uiPacketType == RFL_DELETE_RECORD_PACKET_VER_2)
|
|
{
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_FLAGS_FIELD,
|
|
pRflPacket->uiFlags,
|
|
uiOffset,
|
|
4, pRflPacket->uiFlagsBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
}
|
|
|
|
if (pRflPacket->bHaveTimes)
|
|
{
|
|
|
|
// Output the start time and microseconds
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_START_SECONDS_FIELD,
|
|
pRflPacket->uiStartSeconds,
|
|
uiOffset,
|
|
4, pRflPacket->uiStartSecondsBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_START_MSEC_FIELD,
|
|
pRflPacket->uiStartMicro,
|
|
uiOffset,
|
|
4, pRflPacket->uiStartMicroBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output the end time and microseconds
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_END_SECONDS_FIELD,
|
|
pRflPacket->uiEndSeconds,
|
|
uiOffset,
|
|
4, pRflPacket->uiEndSecondsBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pLastNode, TRUE,
|
|
RFL_END_MSEC_FIELD,
|
|
pRflPacket->uiEndMicro,
|
|
uiOffset,
|
|
4, pRflPacket->uiEndMicroBytes,
|
|
&pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
}
|
|
uiPacketOffset = 0;
|
|
}
|
|
|
|
// Output stuff for add record and modify record
|
|
|
|
if (pRflPacket->uiPacketType == RFL_ADD_RECORD_PACKET ||
|
|
pRflPacket->uiPacketType == RFL_ADD_RECORD_PACKET_VER_2)
|
|
{
|
|
if (RC_BAD( rc = rflExpandRecordPackets( pPool,
|
|
pRflPacket->uiNextPacketAddress,
|
|
0xFF,
|
|
&pParent, uiPacketOffset)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else if (pRflPacket->uiPacketType == RFL_MODIFY_RECORD_PACKET ||
|
|
pRflPacket->uiPacketType == RFL_MODIFY_RECORD_PACKET_VER_2)
|
|
{
|
|
if (RC_BAD( rc = rflExpandRecordPackets( pPool,
|
|
pRflPacket->uiNextPacketAddress,
|
|
0xFF, &pParent, uiPacketOffset)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (RC_BAD( rc) || !pParent)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppForest = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppForest = pParent;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expand an unknown packet.
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandUnkPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pForest = NULL;
|
|
FLMBYTE * pucPacketBody;
|
|
FLMUINT uiBytesRead;
|
|
FLMUINT uiOffset;
|
|
NODE * pTmpNode2;
|
|
|
|
// Output the packet header.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool,
|
|
&pForest)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If there is no packet body, we are done.
|
|
|
|
if (!pRflPacket->uiPacketBodyLength)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Read the packet body from disk.
|
|
|
|
pucPacketBody = &gv_rflBuffer [0];
|
|
f_memset( pucPacketBody, 0, pRflPacket->uiPacketBodyLength);
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
rc = gv_pRflFileHdl->read( uiOffset,
|
|
pRflPacket->uiPacketBodyLength,
|
|
pucPacketBody,
|
|
&uiBytesRead);
|
|
if (RC_BAD( rc))
|
|
{
|
|
if (rc != FERR_IO_END_OF_FILE || !uiBytesRead)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
goto Exit;
|
|
}
|
|
}
|
|
if (!uiBytesRead)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Create a GEDCOM node for the data.
|
|
|
|
if ((pTmpNode2 = GedNodeCreate( pPool, makeTagNum( RFL_DATA_FIELD),
|
|
uiOffset, &rc)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (RC_BAD( rc = GedPutBINARY( pPool, pTmpNode2, pucPacketBody,
|
|
uiBytesRead)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
GedChildGraft( pForest, pTmpNode2, GED_LAST);
|
|
|
|
Exit:
|
|
if (RC_BAD( rc) || !pForest)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
pPool->poolReset( pvMark);
|
|
*ppForest = NULL;
|
|
}
|
|
else
|
|
{
|
|
*ppForest = pForest;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expands an encryption packet (RFL_WRAP_KEY_PACKET or
|
|
RFL_ENABLE_ENCRYPTION_PACKET)
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandEncryptionPacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pParent = NULL;
|
|
NODE * pLastNode;
|
|
NODE * pDataNode;
|
|
FLMUINT uiOffset;
|
|
FLMBYTE * pucNodeData;
|
|
FLMBYTE * pucPacketBody;
|
|
|
|
// Output generic packet header information.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool, &pParent)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Output transaction ID
|
|
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_TRANS_ID_FIELD,
|
|
pRflPacket->uiTransID, uiOffset,
|
|
4, pRflPacket->uiTransIDBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output key len
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_DB_KEY_LEN_FIELD,
|
|
pRflPacket->uiCount, uiOffset,
|
|
2, pRflPacket->uiCountBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 2;
|
|
|
|
// Create a data node, if there is data to output.
|
|
|
|
if ((pDataNode = GedNodeCreate( pPool, makeTagNum( RFL_DATA_FIELD),
|
|
uiOffset, &rc)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
GedChildGraft( pParent, pDataNode, GED_LAST);
|
|
if (((pucNodeData = (FLMBYTE *)GedAllocSpace( pPool, pDataNode,
|
|
FLM_BINARY_TYPE,
|
|
pRflPacket->uiCount)) == NULL) &&
|
|
(pRflPacket->uiCount))
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
pucPacketBody = &gv_rflBuffer [0];
|
|
rc = gv_pRflFileHdl->read( uiOffset,
|
|
pRflPacket->uiCount,
|
|
pucPacketBody,
|
|
NULL);
|
|
|
|
if (pRflPacket->uiCount)
|
|
{
|
|
f_memcpy( pucNodeData, pucPacketBody, pRflPacket->uiCount);
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (RC_BAD( rc) || !pParent)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppForest = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppForest = pParent;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expands a config rfl size packet (RFL_CONFIG_SIZE_EVENT_PACKET)
|
|
*********************************************************************/
|
|
FSTATIC RCODE rflExpandConfigSizePacket(
|
|
RFL_PACKET * pRflPacket,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pParent = NULL;
|
|
NODE * pLastNode;
|
|
FLMUINT uiOffset;
|
|
|
|
// Output generic packet header information.
|
|
|
|
if (RC_BAD( rc = rflExpandPacketHdr( pRflPacket, pPool, &pParent)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Output transaction ID
|
|
|
|
uiOffset = pRflPacket->uiFileOffset + RFL_PACKET_OVERHEAD;
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_TRANS_ID_FIELD,
|
|
pRflPacket->uiTransID, uiOffset,
|
|
4, pRflPacket->uiTransIDBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output size threshhold
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_SIZE_THRESHOLD_FIELD,
|
|
pRflPacket->uiSizeThreshold, uiOffset,
|
|
4, pRflPacket->uiSizeThresholdBytes, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output time interval
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_TIME_INTERVAL_FIELD,
|
|
pRflPacket->uiTimeInterval, uiOffset,
|
|
4, pRflPacket->uiTimeInterval, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
// Output size interval
|
|
|
|
if (RC_BAD( rc = rflPutNum( pPool, pParent, FALSE,
|
|
RFL_SIZE_INTERVAL_FIELD,
|
|
pRflPacket->uiSizeInterval, uiOffset,
|
|
4, pRflPacket->uiSizeInterval, &pLastNode)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
uiOffset += 4;
|
|
|
|
Exit:
|
|
|
|
if (RC_BAD( rc) || !pParent)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppForest = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppForest = pParent;
|
|
}
|
|
return( rc);
|
|
}
|
|
|
|
/********************************************************************
|
|
Desc: Expands a packet into multiple GEDCOM nodes for display of
|
|
all of the subcomponents.
|
|
*********************************************************************/
|
|
RCODE RflExpandPacket(
|
|
NODE * pPacketNode,
|
|
F_Pool * pPool,
|
|
NODE ** ppForest
|
|
)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
void * pvMark = pPool->poolMark();
|
|
NODE * pForest = NULL;
|
|
RFL_PACKET * pRflPacket;
|
|
FLMBOOL bFoundPrev;
|
|
FLMUINT uiDataLen;
|
|
FLMUINT uiLevel;
|
|
RFL_PACKET tmpPacket;
|
|
|
|
// Handle case where nothing was passed in.
|
|
|
|
if (!pPacketNode)
|
|
{
|
|
goto Exit;
|
|
}
|
|
if ((pRflPacket = (RFL_PACKET *)GedValPtr( pPacketNode)) == NULL)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (!pRflPacket->bValidPacketType)
|
|
{
|
|
rc = rflExpandUnkPacket( pRflPacket, pPool, &pForest);
|
|
goto Exit;
|
|
}
|
|
else
|
|
{
|
|
switch (pRflPacket->uiPacketType)
|
|
{
|
|
case RFL_TRNS_BEGIN_PACKET:
|
|
case RFL_TRNS_BEGIN_EX_PACKET:
|
|
case RFL_TRNS_COMMIT_PACKET:
|
|
case RFL_TRNS_ABORT_PACKET:
|
|
rc = rflExpandTrnsPacket( pRflPacket, pPool, &pForest);
|
|
goto Exit;
|
|
case RFL_ADD_RECORD_PACKET:
|
|
case RFL_ADD_RECORD_PACKET_VER_2:
|
|
case RFL_MODIFY_RECORD_PACKET:
|
|
case RFL_MODIFY_RECORD_PACKET_VER_2:
|
|
case RFL_DELETE_RECORD_PACKET:
|
|
case RFL_DELETE_RECORD_PACKET_VER_2:
|
|
case RFL_RESERVE_DRN_PACKET:
|
|
rc = rflExpandRecOpPacket( pRflPacket, pPool, &pForest, 0);
|
|
goto Exit;
|
|
case RFL_CHANGE_FIELDS_PACKET:
|
|
case RFL_DATA_RECORD_PACKET:
|
|
case RFL_ENC_DATA_RECORD_PACKET:
|
|
case RFL_DATA_RECORD_PACKET_VER_3:
|
|
f_memcpy( &tmpPacket, pRflPacket, sizeof( RFL_PACKET));
|
|
bFoundPrev = FALSE;
|
|
if (RC_BAD( rc = rflGetPrevOpPacket( &tmpPacket, &bFoundPrev)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
if (!bFoundPrev)
|
|
{
|
|
uiDataLen = 0xFFFF;
|
|
uiLevel = 0;
|
|
if (pRflPacket->uiPacketType == RFL_DATA_RECORD_PACKET ||
|
|
pRflPacket->uiPacketType == RFL_ENC_DATA_RECORD_PACKET ||
|
|
pRflPacket->uiPacketType == RFL_DATA_RECORD_PACKET_VER_3)
|
|
{
|
|
rc = rflExpandDataPacket( pRflPacket, pPool,
|
|
TRUE, pRflPacket->uiPacketType,
|
|
&pForest, &uiDataLen, &uiLevel);
|
|
}
|
|
else
|
|
{
|
|
rc = rflExpandChangeFieldsPacket( pRflPacket, pPool,
|
|
TRUE, &pForest, &uiDataLen);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = rflExpandRecOpPacket( &tmpPacket, pPool,
|
|
&pForest, pRflPacket->uiFileOffset);
|
|
}
|
|
break;
|
|
case RFL_INDEX_SET_PACKET:
|
|
case RFL_INDEX_SET_PACKET_VER_2:
|
|
rc = rflExpandIndexSetPacket( pRflPacket, pPool, &pForest);
|
|
goto Exit;
|
|
case RFL_BLK_CHAIN_FREE_PACKET:
|
|
rc = rflExpandBlkChainFreePacket( pRflPacket, pPool, &pForest);
|
|
break;
|
|
case RFL_START_UNKNOWN_PACKET:
|
|
rc = rflExpandStartUnknownPacket( pRflPacket, pPool, &pForest);
|
|
goto Exit;
|
|
case RFL_UNKNOWN_PACKET:
|
|
rc = rflExpandUnkPacket( pRflPacket, pPool, &pForest);
|
|
goto Exit;
|
|
case RFL_REDUCE_PACKET:
|
|
rc = rflExpandReducePacket( pRflPacket, pPool, &pForest);
|
|
goto Exit;
|
|
case RFL_UPGRADE_PACKET:
|
|
rc = rflExpandUpgradePacket( pRflPacket, pPool, &pForest);
|
|
goto Exit;
|
|
case RFL_INDEX_SUSPEND_PACKET:
|
|
case RFL_INDEX_RESUME_PACKET:
|
|
rc = rflExpandIndexStatePacket( pRflPacket, pPool, &pForest);
|
|
goto Exit;
|
|
case RFL_WRAP_KEY_PACKET:
|
|
case RFL_ENABLE_ENCRYPTION_PACKET:
|
|
rc = rflExpandEncryptionPacket( pRflPacket, pPool, &pForest);
|
|
goto Exit;
|
|
case RFL_CONFIG_SIZE_EVENT_PACKET:
|
|
rc = rflExpandConfigSizePacket( pRflPacket, pPool, &pForest);
|
|
goto Exit;
|
|
default:
|
|
rc = rflExpandUnkPacket( pRflPacket, pPool, &pForest);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if (RC_BAD( rc) || !pForest)
|
|
{
|
|
if (rc == FERR_IO_END_OF_FILE)
|
|
{
|
|
rc = FERR_OK;
|
|
}
|
|
*ppForest = NULL;
|
|
pPool->poolReset( pvMark);
|
|
}
|
|
else
|
|
{
|
|
*ppForest = pForest;
|
|
}
|
|
return( rc);
|
|
}
|