478 lines
16 KiB
C++
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;
|
|
}
|
|
}
|
|
|
|
*/
|