// // 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& 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 vDirs; SplitString( noun, pIter->GetParentName().GetDelimiter(), vDirs ); for( std::vector::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 ") << std::endl << _T(" pwd ") << std::endl << _T(" ls ") << std::endl << _T(" print ") << 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; } } */