tripwire-open-source/src/tw/textdbviewer.cpp

532 lines
18 KiB
C++

//
// The developer of the original code and/or files is Tripwire, Inc.
// Portions created by Tripwire, Inc. are copyright (C) 2000-2018 Tripwire,
// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights
// reserved.
//
// This program is free software. The contents of this file are subject
// to the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version. You may redistribute it and/or modify it
// only in compliance with the GNU General Public License.
//
// This program is distributed in the hope that it will be useful.
// However, this program is distributed AS-IS WITHOUT ANY
// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS
// FOR A PARTICULAR PURPOSE. Please see the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// Nothing in the GNU General Public License or any other license to use
// the code or files shall permit you to use Tripwire's trademarks,
// service marks, or other intellectual property without Tripwire's
// prior written consent.
//
// If you have any questions, please contact Tripwire, Inc. at either
// info@tripwire.org or www.tripwire.org.
//
///////////////////////////////////////////////////////////////////////////////
// textdbviewer.cpp -- implementation for dbviewer class
//
//=========================================================================
// DIRECTIVES
//=========================================================================
//=========================================================================
// INCLUDES
//=========================================================================
#include "stdtw.h"
#include <fstream>
#include <iomanip>
#include "core/tchar.h"
#include "textdbviewer.h"
#include "core/debug.h"
#include "fcodatabasefile.h"
#include "dbdatasource.h"
#include "fco/fcospec.h"
#include "fco/iterproxy.h"
#include "fco/fcopropvector.h"
#include "fco/fcopropset.h"
#include "fco/fcoprop.h"
#include "core/fsservices.h"
#include "fco/fcospecattr.h"
#include "core/timeconvert.h"
#include "fco/fcopropdisplayer.h"
#include "headerinfo.h"
#include "fco/genreswitcher.h"
#include "core/twlocale.h"
#include "fco/twfactory.h"
#include "fco/fconametranslator.h"
#include "fco/fcoundefprop.h"
#include "tw/twstrings.h"
#include "core/displayencoder.h"
//=========================================================================
// USING NAMESPACE
//=========================================================================
using namespace std;
//=========================================================================
// GLOBALS
//=========================================================================
static const TCHAR* g_sz79Dashes = _T("-------------------------------------------------------------------------------");
static const TCHAR* g_sz79Equals = _T("===============================================================================");
//=========================================================================
// UTIL FUNCTION PROTOTYES
//=========================================================================
static void InitOStream( TOSTREAM* pOut );
static void DisplayFCOProps( const iFCO* const pFCO, const iFCOPropDisplayer* pPD, TOSTREAM* pOut );
static void OutputDatabaseHeader ( const cFCODbHeader& dbHeader, TOSTREAM* pOut );
// Currently we don't have a rule summary. See function definition below
//static void OutputRulesSummary ( const cFCODatabaseFileIter& genreIter, const iFCONameTranslator* pNT, TOSTREAM* pOut );
static void OutputSectionDelimiter( int nString, TOSTREAM* pOut );
static void OutputGenreDelimiter( cGenre::Genre g, TOSTREAM* pOut );
static void OutputObjectSummary( cFCODatabaseFile& rd, TOSTREAM* pOut, int margin );
static void OutputObjectDetail( cFCODatabaseFile& rd, TOSTREAM* pOut );
static void OutputObjectSummary( cFCODatabaseFileIter& genreIter, const iFCONameTranslator* pNT, TOSTREAM* pOut, int margin );
static void OutputObjectDetail( cFCODatabaseFileIter& genreIter, const iFCONameTranslator* pNT, TOSTREAM* pOut );
static void OutputIterChildren ( cDbDataSourceIter dbIter, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, bool fDetails );
static void OutputIterPeers ( cDbDataSourceIter dbIter, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, bool fDetails );
//static void OutputIter ( cDbDataSourceIter& dbIter, const iFCOPropDisplayer* pPD, TOSTREAM* pOut, bool fDetails );
static void PrintFCOShort ( const iFCO* pFCO, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, int margin );
//static void OutputSpecHeader( const cFCODbSpecIter& dbi, TOSTREAM* pOut );
//static void OutputDetailHeader( const cFCODbSpecIter& dbi, int nObjects, TOSTREAM* pOut );
static TSTRING util_Encode( const TSTRING& sIn )
{
static cDisplayEncoder e;
TSTRING sOut = sIn;
e.Encode( sOut );
return sOut;
}
//=========================================================================
// METHOD CODE
//=========================================================================
void cTextDBViewer::PrintDB( cFCODatabaseFile& rd, const TSTRING& strFilename )
{
TOSTREAM* pOut;
TOFSTREAM fileOut;
bool fIsFile = false;
if( strFilename == _T("-") )
{
pOut = &TCOUT;
}
else
{
//Gonna have to insert a lame hack here, since ostr.open DEMANDS a const char*!!
fileOut.open( strFilename.c_str() );
if( fileOut.is_open() )
{
pOut = &fileOut;
fIsFile = true;
}
else
{
ASSERT( false );
throw eArchiveOpen( strFilename, iFSServices::GetInstance()->GetErrString() );
}
}
InitOStream( pOut );
//
// output header, just like it sez....
//
OutputDatabaseHeader( rd.GetHeader(), pOut );
OutputObjectSummary( rd, pOut, DETAILS_MARGIN );
OutputObjectDetail( rd, pOut );
// we're done
(*pOut) << g_sz79Dashes << endl;
(*pOut) << TSS_GetString( cTW, tw::STR_END_OF_DB ) << endl << endl;
(*pOut) << TSS_GetString( cTW, tw::STR_COPYRIGHT ) << endl;
if( fIsFile )
static_cast<TOFSTREAM*>(pOut)->close();
return;
}
///////////////////////////////////////////////////////////////////////////////
// OutputFCO
///////////////////////////////////////////////////////////////////////////////
void cTextDBViewer::OutputFCO( cDbDataSourceIter& dbIter, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, bool fDetails )
{
InitOStream( pOut );
if( dbIter.HasFCOData() )
{
iFCO* pFCO = dbIter.CreateFCO();
if( fDetails )
{
(*pOut) << TSS_GetString( cTW, tw::STR_OBJECT_NAME ) << _T(" ") << pNT->ToStringDisplay( pFCO->GetName() ).c_str() << endl << endl;
DisplayFCOProps( pFCO, pPD, pOut );
(*pOut) << endl << endl;
}
else
PrintFCOShort( pFCO, pPD, pNT, pOut, DETAILS_MARGIN );
pFCO->Release();
}
}
//=========================================================================
// UTIL FUNCTION CODE
//=========================================================================
void InitOStream( TOSTREAM* pOut )
{
// align left
(*pOut).flags( ( (*pOut).flags() & ~std::ios::adjustfield ) | std::ios::left );
}
///////////////////////////////////////////////////////////////////////////////
// PrintFCOShort
///////////////////////////////////////////////////////////////////////////////
static void PrintFCOShort( const iFCO* pFCO, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, int margin )
{
ASSERT( pOut != 0);
TSTRING strDetails;
//
// output "<name of FCO>"\n\t<details of FCO>"
//
(*pOut) << _T(" ");
(*pOut) << pNT->ToStringDisplay( pFCO->GetName() ).c_str();
(*pOut) << endl;
(*pOut) << setw( margin ) << _T("");
pPD->GetDetails( pFCO, strDetails );
(*pOut) << strDetails;
(*pOut) << _T("\n");
}
static void OutputIterChildren( cDbDataSourceIter dbIter, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, bool fDetails )
{
dbIter.Descend();
OutputIterPeers( dbIter, pPD, pNT, pOut, fDetails );
}
static void OutputIterPeers( cDbDataSourceIter dbIter, const iFCOPropDisplayer* pPD, const iFCONameTranslator* pNT, TOSTREAM* pOut, bool fDetails )
{
for ( dbIter.SeekBegin(); ! dbIter.Done(); dbIter.Next() )
{
// TODO: this obviously needs to be expanded upon.
cTextDBViewer::OutputFCO( dbIter, pPD, pNT, pOut, fDetails );
if( dbIter.CanDescend() )
OutputIterChildren( dbIter, pPD, pNT, pOut, fDetails );
}
}
static void OutputDatabaseHeader( const cFCODbHeader& dbHeader, TOSTREAM* pOut )
{
const int headerColumnWidth = 30;
(*pOut) << TSS_GetString( cTW, tw::STR_DBPRINT_TITLE ) << endl << endl;
(*pOut).width(headerColumnWidth);
(*pOut) << TSS_GetString( cTW, tw::STR_DB_GENERATED_BY ) << util_Encode( dbHeader.GetCreator() ) << endl;
TSTRING tstrDummy;
int64 i64CreateTime = dbHeader.GetCreationTime();
(*pOut).width(headerColumnWidth);
(*pOut) << TSS_GetString( cTW, tw::STR_DB_CREATED_ON ) << cTWLocale::FormatTime( i64CreateTime, tstrDummy ).c_str() << endl;
(*pOut).width(headerColumnWidth);
(*pOut) << TSS_GetString( cTW, tw::STR_DB_LAST_UPDATE );
int64 i64LastDBUTime = dbHeader.GetLastDBUpdateTime();
if( i64LastDBUTime == 0 )
{
(*pOut) << TSS_GetString( cTW, tw::STR_NEVER ) << endl << endl;
}
else
{
(*pOut) << cTWLocale::FormatTime( i64LastDBUTime, tstrDummy ).c_str() << endl << endl;
}
OutputSectionDelimiter( tw::STR_DB_SUMMARY, pOut );
(*pOut).width(headerColumnWidth);
(*pOut) << TSS_GetString( cTW, tw::STR_HOST_NAME ) << dbHeader.GetSystemName().c_str() << endl;
(*pOut).width(headerColumnWidth);
(*pOut) << TSS_GetString( cTW, tw::STR_HOST_IP ) << dbHeader.GetIPAddress() << endl;
(*pOut).width(headerColumnWidth);
(*pOut) << TSS_GetString( cTW, tw::STR_HOST_ID );
if(! dbHeader.GetHostID().empty() )
(*pOut) << dbHeader.GetHostID() << endl;
else
(*pOut) << TSS_GetString( cTW, tw::STR_NONE ) << endl;
(*pOut) << setw(headerColumnWidth)
<< TSS_GetString( cTW, tw::STR_POLICY_FILE_USED )
<< util_Encode( dbHeader.GetPolicyFilename() )
<< endl;
(*pOut) << setw(headerColumnWidth)
<< TSS_GetString( cTW, tw::STR_CONFIG_FILE_USED )
<< util_Encode( dbHeader.GetConfigFilename() )
<< endl;
(*pOut) << setw(headerColumnWidth)
<< TSS_GetString( cTW, tw::STR_DB_FILE_USED )
<< util_Encode( dbHeader.GetDBFilename() )
<< endl;
(*pOut) << setw(headerColumnWidth)
<< TSS_GetString( cTW, tw::STR_CMD_LINE_USED )
<< util_Encode( dbHeader.GetCommandLineParams() )
<< endl
<< endl;
}
#if 0
// The rules summary is not working due to changes in the databasse infrastructure. Until
// we hear different from the product manager, it is out of here.
static void OutputRulesSummary(const cFCODatabaseFileIter& genreIter, const iFCONameTranslator* pNT, TOSTREAM* pOut )
{
const cHierDatabase& db = genreIter.GetDb();
// these should add up to 79
const int nameWidth = 50;
const int numObjectsWidth = 10;
(*pOut) << g_sz79Dashes << endl;
(*pOut) << TSS_GetString( cTW, tw::STR_RULE_SUMMARY ) << endl;
(*pOut) << g_sz79Dashes << endl << endl;
(*pOut).width(nameWidth);
(*pOut) << TSS_GetString( cTW, tw::STR_RULE_NAME );
(*pOut).width(numObjectsWidth);
(*pOut) << TSS_GetString( cTW, tw::STR_OBJECTS ) << endl;
(*pOut) << setw( nameWidth ) << _T("---------");
(*pOut) << setw( numObjectsWidth ) << _T("-------");
(*pOut) << endl;
// output spec stats
cFCOSpecListCanonicalIter specIter( genreIter.GetSpecList() );
// iterate over all database elements
int nTotalObjects = 0;
for( specIter.SeekBegin(); !specIter.Done(); specIter.Next() )
{
(*pOut) << setw( nameWidth ) << specIter.Spec()->GetName();
// if the name is too long, put it on its own line
if( specIter.Spec()->GetName().length() >= nameWidth )
{
(*pOut) << endl;
// output space holder
(*pOut).width(nameWidth);
(*pOut) << _T("");
}
(*pOut).width(numObjectsWidth);
(*pOut) << _T("TODO");
//(*pOut) << specIter.GetFCOSet()->Size(); TODO: Do this right
(*pOut) << endl;
}
(*pOut) << endl;
// NOTE 4 Jan 99 mdb -- this used to use dbHeader.GetTotalObjectsScanned() but it was not always consistent with the
// total number of objects in the database. TODO -- if we are really not going to use this number, then we should
// not store it in the database at all.
//
(*pOut) << TSS_GetString( cTW, tw::STR_TOTAL_NUM_FILES );
//(*pOut) << _T(" ") << nTotalObjects << endl;
(*pOut) << _T("TODO") << endl;
(*pOut) << endl;
}
#endif
void OutputSectionDelimiter( int nString, TOSTREAM* pOut )
{
(*pOut) << g_sz79Equals << endl;
(*pOut) << TSS_GetString( cTW, nString ) << endl;
(*pOut) << g_sz79Equals << endl << endl;
}
void OutputGenreDelimiter( cGenre::Genre g, TOSTREAM* pOut )
{
(*pOut) << g_sz79Dashes << endl;
(*pOut) << _T("# ") << TSS_GetString( cTW, tw::STR_SECTION );
(*pOut) << _T(": ") << cGenreSwitcher::GetInstance()->GenreToString( g, true ) << endl;
(*pOut) << g_sz79Dashes << endl << endl;
}
void OutputObjectSummary( cFCODatabaseFile& rd, TOSTREAM* pOut, int margin )
{
OutputSectionDelimiter( tw::STR_OBJECT_SUMMARY, pOut );
cFCODatabaseFileIter genreIter(rd);
for (genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next())
{
cGenreSwitcher::GetInstance()->SelectGenre( (cGenre::Genre) genreIter.GetGenre() );
iFCONameTranslator* pNT = iTWFactory::GetInstance()->GetNameTranslator();
OutputGenreDelimiter( (cGenre::Genre) genreIter.GetGenre(), pOut );
// Currently we don't have a rule summary. See function definition below
//OutputRulesSummary( genreIter, pNT, pOut);
OutputObjectSummary( genreIter, pNT, pOut, margin );
}
}
void OutputObjectSummary( cFCODatabaseFileIter& genreIter, const iFCONameTranslator* pNT, TOSTREAM* pOut, int margin )
{
const cDbDataSourceIter dbIter( &genreIter.GetDb() );
ASSERT(dbIter.AtRoot());
(*pOut) << setw( margin ) << _T("");
TSTRING strBuf;
(*pOut) << genreIter.GetGenreHeader().GetPropDisplayer()->GetDetailsHeader( strBuf, margin ).c_str() << endl;
OutputIterPeers( dbIter, genreIter.GetGenreHeader().GetPropDisplayer(), pNT, pOut, false );
(*pOut) << endl;
}
void OutputObjectDetail( cFCODatabaseFile& rd, TOSTREAM* pOut )
{
OutputSectionDelimiter( tw::STR_OBJECT_DETAIL, pOut );
cFCODatabaseFileIter genreIter(rd);
for (genreIter.SeekBegin(); !genreIter.Done(); genreIter.Next())
{
cGenreSwitcher::GetInstance()->SelectGenre( (cGenre::Genre) genreIter.GetGenre() );
iFCONameTranslator* pNT = iTWFactory::GetInstance()->GetNameTranslator();
OutputGenreDelimiter( (cGenre::Genre) genreIter.GetGenre(), pOut );
OutputObjectDetail( genreIter, pNT, pOut );
}
}
void OutputObjectDetail( cFCODatabaseFileIter& genreIter, const iFCONameTranslator* pNT, TOSTREAM* pOut )
{
const cDbDataSourceIter dbIterDetails(&genreIter.GetDb());
OutputIterPeers( dbIterDetails, genreIter.GetGenreHeader().GetPropDisplayer(), pNT, pOut, true);
(*pOut) << endl;
}
/*
static void OutputDetailHeader( const cFCODbSpecIter &dbi, int nObjects, TOSTREAM* pOut )
{
(*pOut) << g_sz79Dashes << _T( "\n" );
(*pOut) << TSS_GetString( cTW, tw::STR_FILE_DETAIL ) << endl;
TOSTRINGSTREAM ostr2;
ostr2 << TSS_GetString( cTW, tw::STR_RULE_NAME ) << _T(": ") << dbi.GetSpec()->GetName().c_str();
ostr2 << _T( " (" ) << dbi.GetSpec()->GetStartPoint().AsString().c_str() << _T( ")" ) << endl;
(*pOut) << ostr2.str().c_str();
(*pOut) << TSS_GetString( cTW, tw::STR_TOTAL_NUM_FILES ) << _T(" ") << nObjects << endl;
(*pOut) << g_sz79Dashes << endl << endl;
}
*/
/*
static void OutputSpecHeader( const cFCODbSpecIter &dbi, TOSTREAM* pOut )
{
(*pOut) << g_sz79Dashes << _T( "\n" );
TOSTRINGSTREAM ostr2;
ostr2 << TSS_GetString( cTW, tw::STR_RULE_NAME ) << _T(": ") << dbi.GetSpec()->GetName().c_str();
ostr2 << _T( " (" ) << dbi.GetSpec()->GetStartPoint().AsString().c_str() << _T( ")" ) << endl;
(*pOut) << ostr2.str().c_str();
(*pOut) << g_sz79Dashes << _T( "\n" );
}
*/
void DisplayFCOProps( const iFCO* const pFCO, const iFCOPropDisplayer* pPD, TOSTREAM* pOut )
{
ASSERT( pOut != 0);
ASSERT( pFCO != 0);
const int attrNameWidth = 24;
const int attrValueWidth = 28;
// output header
// TODO: make these constants into enums
(*pOut).width( attrNameWidth );
(*pOut) << TSS_GetString( cTW, tw::STR_ATTRIBUTES );
(*pOut).width( attrValueWidth );
(*pOut) << TSS_GetString( cTW, tw::STR_ATTR_VALUE );
(*pOut) << endl;
(*pOut).width( attrNameWidth );
(*pOut) << _T("-------------");
(*pOut).width( attrValueWidth );
(*pOut) << _T("-----------");
(*pOut) << endl;
int iNumProps = pFCO->GetPropSet()->GetNumProps();
for( int j = 0; j < iNumProps; j++ )
{
// output if prop is in FCO, and prop is not cFCOUndefinedProp
if(
pFCO->GetPropSet()->GetValidVector().ContainsItem( j )
&&
pFCO->GetPropSet()->GetPropAt( j )->GetType() != cFCOUndefinedProp::GetInstance()->GetType()
)
{
TSTRING strProp;
// output property name
(*pOut).width( attrNameWidth );
(*pOut) << pFCO->GetPropSet()->GetPropName(j);
(*pOut).width( attrValueWidth );
(*pOut) << pPD->PropAsString( pFCO, j, attrNameWidth, 0 );
(*pOut) << _T("\n");
}
}
}