// // 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 #include #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(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 ""\n\t
" // (*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"); } } }