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

478 lines
16 KiB
C++

//
// The developer of the original code and/or files is Tripwire, Inc.
// Portions created by Tripwire, Inc. are copyright (C) 2000 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.
//
///////////////////////////////////////////////////////////////////////////////
// dbexplore.cpp
//
#include "stdtw.h"
#include "dbexplore.h"
#include "fcodatabasefile.h"
#include "dbdatasource.h"
#include "core/debug.h"
#include "core/error.h"
#include "fco/fcopropdisplayer.h"
#include "fco/fcopropvector.h"
#include "fco/fcopropset.h"
#include "fco/fcoprop.h"
#include "fco/genreswitcher.h"
#include "fco/twfactory.h"
#include "fco/fconametranslator.h"
//
// TODO -- make an "associate with new genre" method for the db iter so we don't have to
// delete and create a new one when we switch genres.
//
static inline bool IsSpace( TCHAR c )
{
return ( (c == _T(' ')) || (c == _T('\t')) || (c == _T('\r')) || (c == _T('\n')) || (c == _T('\0')) );
}
static inline bool IsEnd( TCHAR c )
{
return ( (c == _T('\0')) );
}
///////////////////////////////////////////////////////////////////////////////
// GetNoun
// note -- you can only call this once after the verb (it eats the rest
// of the line!)
///////////////////////////////////////////////////////////////////////////////
static void GetNoun( TSTRING& noun )
{
static TSTRING prevNoun;
TCHAR buf[1024];
TCIN.getline( buf, 1024 );
//
// find the end of the noun...
//
TCHAR* pStart = buf;
TCHAR* end = &buf[1023];
while( IsSpace(*pStart) && (! IsEnd(*pStart)) && (pStart < end) )
pStart++;
if( IsEnd( *pStart ) || (pStart >= end) )
{
// no noun!
noun = _T("");
return;
}
TCHAR* pCur = pStart;
bool bQuote = false;
if( *pCur == _T('\"') )
{
bQuote = true;
pCur++;
pStart++;
}
while( pCur < end )
{
if( (! bQuote) && IsSpace(*pCur) )
break;
if( *pCur == _T('\"') && bQuote)
break;
pCur++;
}
noun.assign(pStart, (pCur - pStart));
if( noun.compare( _T("!$") ) == 0 )
{
noun = prevNoun;
}
prevNoun = noun;
}
///////////////////////////////////////////////////////////////////////////////
// SeekTo -- seeks to the named noun; this takes care of interpriting special
// nouns. If the seek fails, then Done() is true and false is returned.
// If noun is a special character, then it is altered to what it mapped to.
///////////////////////////////////////////////////////////////////////////////
static bool SeekTo(cDbDataSourceIter* pIter, TSTRING& noun )
{
if( noun[0] == _T('*') )
{
// interprite the rest of the string as a number index to seek to...
int index = _ttoi( &noun[1] );
if( index < 0 )
return false;
pIter->SeekBegin();
for( int i=0; ((i < index) && (! pIter->Done())); i++, pIter->Next() )
{
}
if( pIter->Done() )
return false;
noun = pIter->GetShortName();
return true;
}
else
return ( pIter->SeekTo( noun.c_str() ) );
}
///////////////////////////////////////////////////////////////////////////////
// PrintFCO
///////////////////////////////////////////////////////////////////////////////
static void PrintFCO( const iFCO* pFCO, const iFCOPropDisplayer* pDisplayer )
{
TCOUT.setf(std::ios::left);
TCOUT << _T("------- ")
<< iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( pFCO->GetName() )
<< _T(" -------")
<< std::endl;
//
// iterate over all of the properties
//
const iFCOPropSet* pPropSet = pFCO->GetPropSet();
cFCOPropVector v = pPropSet->GetValidVector();
for( int i=0; i < pPropSet->GetNumProps(); i++ )
{
if( v.ContainsItem( i ) )
{
TCOUT << _T("[");
TCOUT.width(2);
TCOUT << i << _T("]") ;
TCOUT.width(25);
TCOUT << pPropSet->GetPropName(i);
TCOUT.width(0);
TCOUT << pDisplayer->PropAsString( pFCO, i ) << std::endl;
}
}
TCOUT << _T("--------------------------------------------") << std::endl;
}
static void SplitString( const TSTRING& str, TCHAR c, std::vector<TSTRING>& vStrings )
{
vStrings.clear();
TSTRING::const_iterator i, prev;
for( prev = i = str.begin(); i != str.end(); ++i )
{
if( *i == c )
{
vStrings.push_back(TSTRING());
vStrings.back().assign( prev, i );
prev = i+1;
}
}
if( prev != i )
{
vStrings.push_back(TSTRING());
vStrings.back().assign( prev, i );
}
}
///////////////////////////////////////////////////////////////////////////////
// Execute
///////////////////////////////////////////////////////////////////////////////
void cDbExplore::Execute( cFCODatabaseFileIter& dbIter )
{
ASSERT( ! dbIter.Done() );
cDbDataSourceIter* pIter = new cDbDataSourceIter( &dbIter.GetDb(), dbIter.GetGenre() );
const iFCOPropDisplayer* pDisplayer = dbIter.GetGenreHeader().GetPropDisplayer();
////////////////////////////
// the main event loop...
////////////////////////////
while( true )
{
TSTRING verb, noun;
TCOUT << _T(">>");
TCIN >> verb;
//
// ok, now we switch on the command...
//
//-----------------------------------------------------------------
// quit
//-----------------------------------------------------------------
if( verb.compare( _T("quit") ) == 0 )
{
// the quit command...
break;
}
//-----------------------------------------------------------------
// print
//-----------------------------------------------------------------
if( verb.compare( _T("print") ) == 0 )
{
GetNoun(noun);
if( SeekTo( pIter, noun ) )
{
if( pIter->HasFCOData() )
{
iFCO* pFCO = pIter->CreateFCO();
PrintFCO( pFCO, pDisplayer );
pFCO->Release();
}
else
{
TCOUT << _T("Object has no data associated with it.") << std::endl;
}
}
else
{
TCOUT << _T("Unable to find object ") << noun << std::endl;
}
}
//-----------------------------------------------------------------
// pwd
//-----------------------------------------------------------------
else if( verb.compare( _T("pwd") ) == 0 )
{
TCOUT << iTWFactory::GetInstance()->GetNameTranslator()->ToStringDisplay( pIter->GetParentName() ) << std::endl;
}
//-----------------------------------------------------------------
// ls
//-----------------------------------------------------------------
else if( verb.compare( _T("ls") ) == 0 )
{
int cnt = 0;
for( pIter->SeekBegin(); ! pIter->Done(); pIter->Next(), cnt++ )
{
TCOUT << _T("[") << cnt ;
if( pIter->CanDescend() )
{
TCOUT << _T("]*\t") ;
}
else
{
TCOUT << _T("]\t") ;
}
TCOUT << pIter->GetShortName() << std::endl;
}
}
//-----------------------------------------------------------------
// cd
//-----------------------------------------------------------------
else if( verb.compare( _T("cd") ) == 0 )
{
GetNoun(noun);
std::vector<TSTRING> vDirs;
SplitString( noun, pIter->GetParentName().GetDelimiter(), vDirs );
for( std::vector<TSTRING>::iterator i = vDirs.begin(); i != vDirs.end(); ++i )
{
if( i->compare( _T("..") ) == 0 )
{
if( pIter->AtRoot() )
{
TCOUT << _T("Can't ascend above root.") << std::endl;
break;
}
else
{
TCOUT << _T("Ascending...") << std::endl;
pIter->Ascend();
}
}
else
{
if( SeekTo( pIter, *i ) )
{
if( pIter->CanDescend() )
{
TCOUT << _T("Descending into ") << *i << std::endl;
pIter->Descend();
}
else
{
TCOUT << *i << _T(" has no children; can't descend.") << std::endl;
break;
}
}
else
{
TCOUT << _T("Unable to find object ") << *i << std::endl;
break;
}
}
}
}
//-----------------------------------------------------------------
// cg
//-----------------------------------------------------------------
else if( verb.compare( _T("cg") ) == 0 )
{
GetNoun(noun);
cGenre::Genre newGenre = cGenreSwitcher::GetInstance()->StringToGenre( noun.c_str() );
if (newGenre != cGenre::GENRE_INVALID)
{
dbIter.SeekToGenre( newGenre );
if( !dbIter.Done() )
{
TCOUT << _T("Changing to Genre ") << noun << std::endl;
//
// create a new db iter for the new genre (db iters can only be
// assocaited with a single genre :-( )
//
delete pIter;
pIter = new cDbDataSourceIter( &dbIter.GetDb(), newGenre );
}
else
{
TCOUT << _T("Unable to find Genre ") << noun << std::endl;
}
}
else
{
TCOUT << _T("Invalid Genre ") << noun << std::endl;
}
}
//-----------------------------------------------------------------
// pwg
//-----------------------------------------------------------------
else if( verb.compare( _T("pwg") ) == 0 )
{
TCOUT << _T("Current Genre: ") << cGenreSwitcher::GetInstance()->GenreToString( (cGenre::Genre)dbIter.GetGenre(), true ) << std::endl;
}
//-----------------------------------------------------------------
// help
//-----------------------------------------------------------------
if( verb.compare( _T("help") ) == 0 )
{
TCOUT << _T("Commands: ") << std::endl
<< _T(" cd <dir_name>") << std::endl
<< _T(" pwd ") << std::endl
<< _T(" ls ") << std::endl
<< _T(" print <object_name>") << std::endl
<< _T(" cg (FS | NTFS | NTREG)")<< std::endl
<< _T(" pwg") << std::endl
<< _T(" quit") << std::endl;
}
// make sure the file is still valid...
//
/*
#ifdef _BLOCKFILE_DEBUG
db.AssertAllBlocksValid() ;
#endif
*/
}
delete pIter;
TCOUT << _T("Exiting...") << std::endl;
}
///////////////////////////////////////////////////////////////////////////////
//
// old stuff
//
///////////////////////////////////////////////////////////////////////////////
/*
//-----------------------------------------------------------------
// mkdir
//-----------------------------------------------------------------
else if( verb.compare( _T("mkdir") ) == 0 )
{
GetNoun(noun);
TCOUT << "Making a child of " << noun << std::endl;
if( iter.SeekTo( noun.c_str() ) )
{
iter.AddChildArray();
}
else
{
TCOUT << "Unable to find object " << noun << std::endl;
}
}
//-----------------------------------------------------------------
// mk
//-----------------------------------------------------------------
else if( verb.compare( _T("mk") ) == 0 )
{
GetNoun(noun);
TCOUT << "Making object " << noun << std::endl;
if( iter.SeekTo( noun.c_str() ) )
{
TCOUT << "Error: object already exists!" << std::endl;
}
else
{
iter.AddFCO( noun, 0 ); // add a null fco for now
}
}
//-----------------------------------------------------------------
// rmdir
//-----------------------------------------------------------------
// TODO -- still needs to be implemented in the iterator class!
//
else if( verb.compare( _T("rmdir") ) == 0 )
{
GetNoun(noun);
TCOUT << "Removing the child of " << noun << std::endl;
if( iter.SeekTo( noun.c_str() ) )
{
//TODO -- check that it has an empty child
iter.DeleteChildArray();
}
else
{
TCOUT << "Unable to find object " << noun << std::endl;
}
}
//-----------------------------------------------------------------
// rm
//-----------------------------------------------------------------
else if( verb.compare( _T("rm") ) == 0 )
{
GetNoun(noun);
TCOUT << "Removing object " << noun << std::endl;
if( iter.SeekTo( noun.c_str() ) )
{
if( iter.CanDescend() )
{
TCOUT << "Can't delete object; it still has children." << std::endl;
}
else
{
iter.RemoveFCO();
}
}
else
{
TCOUT << "Unable to find object " << noun << std::endl;
}
}
*/