#include #include #include #include #include #include static auto JoinAtIndex( QStringList list, int index, QString sep ) -> QString { auto string = QString(); for ( int i = 0; i < list.size(); i++ ) { if ( i == index ) break; string = string + list[ i ] + sep; } return string; } auto PathGetParent( QString MainPath ) -> QString { auto Path = MainPath.toStdString(); auto Indx = 0; for ( Indx = Path.size() ;; Indx-- ) if ( Path[ Indx ] == '\\' ) break; Path = Path.substr( 0, Indx ); spdlog::info( "Path: {}", Path ); return QString( Path.c_str() ); } void FileBrowser::setupUi( QWidget* FileBrowser ) { FileBrowserWidget = FileBrowser; auto MenuStyle = QString( "QMenu {" " background-color: #282a36;" " color: #f8f8f2;" " border: 1px solid #44475a;" "}" "QMenu::separator {" " background: #44475a;" "}" "QMenu::item:selected {" " background: #44475a;" "}" "QAction {" " background-color: #282a36;" " color: #f8f8f2;" "}" ); if ( FileBrowser->objectName().isEmpty() ) FileBrowser->setObjectName( QString::fromUtf8( "FileBrowser" ) ); gridLayout = new QGridLayout( FileBrowser ); gridLayout->setObjectName( QString::fromUtf8( "gridLayout" ) ); splitter = new QSplitter( FileBrowser ); splitter->setObjectName( QString::fromUtf8( "splitter" ) ); splitter->setOrientation( Qt::Horizontal ); FileBrowserTree = new QTreeWidget( splitter ); FileBrowserTree->setObjectName( QString::fromUtf8( "FileBrowserTree" ) ); FileBrowserListWidget = new QWidget( splitter ); FileBrowserListWidget->setObjectName( QString::fromUtf8( "FileBrowserListWidget" ) ); formLayout = new QFormLayout( FileBrowserListWidget ); formLayout->setObjectName( QString::fromUtf8( "formLayout" ) ); ButtonGoUpDir = new QPushButton( FileBrowserListWidget ); ButtonGoUpDir->setObjectName( QString::fromUtf8( "ButtonGoUpDir" ) ); formLayout->setWidget( 0, QFormLayout::LabelRole, ButtonGoUpDir ); InputFileBrowserPath = new QLineEdit( FileBrowserListWidget ); InputFileBrowserPath->setObjectName( QString::fromUtf8( "InputFileBrowserPath" ) ); formLayout->setWidget( 0, QFormLayout::FieldRole, InputFileBrowserPath ); TableFileBrowser = new QTableWidget( FileBrowserListWidget ); TableFileBrowser->setObjectName( QString::fromUtf8( "TableFileBrowser" ) ); TableFileBrowser->setEnabled( true ); TableFileBrowser->setShowGrid( false ); TableFileBrowser->setSortingEnabled( false ); TableFileBrowser->setWordWrap( true ); TableFileBrowser->setCornerButtonEnabled( true ); TableFileBrowser->horizontalHeader()->setVisible( true ); TableFileBrowser->setSelectionBehavior( QAbstractItemView::SelectRows ); TableFileBrowser->setContextMenuPolicy( Qt::CustomContextMenu ); TableFileBrowser->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch ); TableFileBrowser->verticalHeader()->setVisible(false); TableFileBrowser->verticalHeader()->setStretchLastSection( false ); TableFileBrowser->verticalHeader()->setDefaultSectionSize( 12 ); TableFileBrowser->setFocusPolicy( Qt::NoFocus ); if ( TableFileBrowser->columnCount() < 3 ) TableFileBrowser->setColumnCount( 3 ); TableFileBrowser->setHorizontalHeaderItem( 0, new QTableWidgetItem( "Name" ) ); TableFileBrowser->setHorizontalHeaderItem( 1, new QTableWidgetItem( "Size" ) ); TableFileBrowser->setHorizontalHeaderItem( 2, new QTableWidgetItem( "Modified" ) ); formLayout->setWidget( 1, QFormLayout::SpanningRole, TableFileBrowser ); splitter->addWidget( FileBrowserTree ); splitter->addWidget( FileBrowserListWidget ); splitter->setSizes( QList() << 1 << 250 ); gridLayout->addWidget( splitter, 0, 0, 1, 1 ); MenuFileBrowserTable = new QMenu( this ); MenuFileBrowserTable->setStyleSheet( MenuStyle ); // MenuFileBrowserTable->addAction( "Remove", this, &FileBrowser::onTableMenuRemove ); MenuFileBrowserTable->addAction( "Download", this, &FileBrowser::onTableMenuDownload ); MenuFileBrowserTable->addAction( "Reload", this, &FileBrowser::onTableMenuReload ); // MenuFileBrowserTable->addAction( "Mkdir", this, &FileBrowser::onTableMenuMkdir ); TableFileBrowser->addAction( MenuFileBrowserTable->menuAction() ); MenuFileBrowserTree = new QMenu( this ); MenuFileBrowserTree->setStyleSheet( MenuStyle ); // MenuFileBrowserTree->addAction( "List Drives", this, &FileBrowser::onTreeMenuListDrives ); // MenuFileBrowserTree->addAction( "Remove", this, &FileBrowser::onTreeMenuRemove ); // MenuFileBrowserTree->addAction( "Reload", this, &FileBrowser::onTreeMenuReload ); // MenuFileBrowserTree->addAction( "Mkdir", this, &FileBrowser::onTreeMenuMkdir ); FileBrowserTree->addAction( MenuFileBrowserTree->menuAction() ); retranslateUi( ); QObject::connect( TableFileBrowser, &QTableWidget::cellDoubleClicked, this, &FileBrowser::onTableDoubleClick ); QObject::connect( TableFileBrowser, &QTableWidget::customContextMenuRequested, this, &FileBrowser::onTableContextMenu ); QObject::connect( FileBrowserTree, &QTreeWidget::customContextMenuRequested, this, &FileBrowser::onTableContextMenu ); QObject::connect( ButtonGoUpDir, &QPushButton::clicked, this, &FileBrowser::onButtonUp ); QObject::connect( InputFileBrowserPath, &QLineEdit::returnPressed, this, &FileBrowser::onInputPath ); QMetaObject::connectSlotsByName( FileBrowser ); } void FileBrowser::retranslateUi() { auto Pix = QPixmap( ":/icons/FileBrowserFolder" ); FileBrowserWidget->setWindowTitle( QCoreApplication::translate("FileBrowser", "FileBrowser", nullptr)); FileBrowserTree->headerItem()->setText( 0, "Files" ); ButtonGoUpDir->setIcon( QIcon( Pix ) ); ButtonGoUpDir->setIconSize( Pix.rect().size() ); } void FileBrowser::AddData( QJsonDocument JsonData ) { auto Path = QString(); auto Files = QJsonDocument(); auto Data = FileDirData(); if ( ! JsonData[ "Path" ].isString() ) { spdlog::error( "[FileBrowser::AddData] Path is not string" ); return; } if ( ! JsonData[ "Files" ].isArray() ) { spdlog::error( "[FileBrowser::AddData] Files is not an array" ); return; } Path = QByteArray::fromBase64( JsonData[ "Path" ].toString().toLocal8Bit() ); Path.replace( "\\*", "" ); for ( int i = 0; i < DirData.size(); i++ ) { if ( Path.compare( DirData[ i ].Path ) == 0 ) { spdlog::info( "Path already exists. remove it" ); DirData.erase( DirData.begin() + i ); } } Files = QJsonDocument( JsonData[ "Files" ].toArray() ); Data = FileDirData { .Path = Path, .Data = Files }; if ( Files.isArray() ) { for ( auto data : Files.array() ) { if ( data.isObject() ) { auto Type = data.toObject()[ "Type" ].toString(); auto Name = data.toObject()[ "Name" ].toString(); auto Size = data.toObject()[ "Size" ].toString(); auto Modified = data.toObject()[ "Modified" ].toString(); auto fileData = FileData{ .Path = Path, .Type = Type, .Name = Name, .Size = Size, .Modified = Modified, }; Data.Files.push_back( fileData ); } else spdlog::error( "Files isn't array" ); } } else spdlog::error( "Files isn't array" ); DirData.push_back( Data ); for ( auto& data : Data.Files ) { TableAddData( data ); // TreeAddData( data ); } TreeUpdate(); Path.replace( "\\*", "" ); InputFileBrowserPath->setText( Path ); } void FileBrowser::TreeAddData( FileData Data ) { spdlog::info( "Append tree" ); } void FileBrowser::TableAddData( FileData Data ) { auto ItemName = new FileBrowserTableItem(); auto ItemSize = new FileBrowserTableItem(); auto ItemModified = new FileBrowserTableItem(); if ( TableFileBrowser->rowCount() < 1 ) TableFileBrowser->setRowCount( 1 ); else TableFileBrowser->setRowCount( TableFileBrowser->rowCount() + 1 ); if ( Data.Type.compare( "dir" ) == 0 ) ItemName->setIcon( QIcon( ":/icons/FileBrowserFolder" ) ); else ItemName->setIcon( QIcon( ":/icons/FileBrowserFile" ) ); ItemName->setText( Data.Name ); ItemName->setFlags( ItemName->flags() ^ Qt::ItemIsEditable ); ItemName->setTextAlignment( Qt::AlignLeft ); ItemSize->setText( Data.Size ); ItemSize->setFlags( ItemSize->flags() ^ Qt::ItemIsEditable ); ItemSize->setTextAlignment( Qt::AlignLeft ); ItemModified->setText( Data.Modified ); ItemModified->setFlags( ItemModified->flags() ^ Qt::ItemIsEditable ); ItemModified->setTextAlignment( Qt::AlignLeft ); ItemName->Data = Data; ItemSize->Data = Data; ItemModified->Data = Data; TableFileBrowser->setItem( TableFileBrowser->rowCount() - 1, 0, ItemName ); TableFileBrowser->setItem( TableFileBrowser->rowCount() - 1, 1, ItemSize ); TableFileBrowser->setItem( TableFileBrowser->rowCount() - 1, 2, ItemModified ); } void FileBrowser::onTableDoubleClick( int row, int column ) { auto Item = ( ( FileBrowserTableItem* ) TableFileBrowser->item( row, column ) ); if ( Item->Data.Type.compare( "dir" ) == 0 ) { QString Path = Item->Data.Path + "\\" + Item->Data.Name; TableClear(); ChangePathAndSendRequest(Path ); return; } } void FileBrowser::onTreeDoubleClick() { } void FileBrowser::ChangePathAndSendRequest( QString Path ) { Path.replace( "\\*", "" ); InputFileBrowserPath->setText( Path ); for ( auto& Session : HavocX::Teamserver.Sessions ) { if ( Session.Name.compare( SessionID ) == 0 ) { Session.InteractedWidget->DemonCommands->Execute.FS( Util::gen_random( 8 ).c_str(), "dir;ui", Path ); } } } void FileBrowser::TableClear() { // TODO: free items for ( int i = TableFileBrowser->rowCount() - 1; i >= 0; i-- ) TableFileBrowser->removeRow( i ); } void FileBrowser::onButtonUp() { auto Path = PathGetParent( InputFileBrowserPath->text() ); TableClear(); ChangePathAndSendRequest( Path ); } void FileBrowser::onTableMenuDownload(){ auto Item = ( ( FileBrowserTableItem* ) TableFileBrowser->item( TableFileBrowser->currentRow(), 0 ) ); if ( Item->Data.Type.compare( "dir" ) == 0 ) { auto box = QMessageBox(); box.setWindowTitle( "FileBrowser error" ); box.setText( "Please select the file type correctly" ); box.setIcon( QMessageBox::NoIcon ); box.setStyleSheet( FileRead( ":/stylesheets/MessageBox" ) ); box.exec(); return; }else{ QString Path = Item->Data.Path + "\\" + Item->Data.Name; for ( auto& Session : HavocX::Teamserver.Sessions ) { if ( Session.Name.compare( SessionID ) == 0 ) { QString TaskID = Session.InteractedWidget->TaskInfo(true,Util::gen_random( 8 ).c_str(),"Tasked demon to download a file "+Path); Session.InteractedWidget->DemonCommands->Execute.FS( TaskID, "download", Path.toLocal8Bit().toBase64() ); } } return; } } void FileBrowser::onTableContextMenu( const QPoint &pos ) { if ( ! TableFileBrowser->itemAt( pos ) ) return; MenuFileBrowserTable->popup( TableFileBrowser->horizontalHeader()->viewport()->mapToGlobal( pos ) ); } void FileBrowser::onTreeContextMenu( const QPoint &pos ) { /*if ( ! FileBrowserTree->itemAt( pos ) ) return; MenuFileBrowserTree->popup( TableFileBrowser->horizontalHeader()->viewport()->mapToGlobal( pos ) );*/ } void FileBrowser::onTableMenuMkdir() { } void FileBrowser::onTableMenuReload() { auto Item = ( ( FileBrowserTableItem* ) TableFileBrowser->item( TableFileBrowser->currentRow(), 0 ) ); if(!Item->Data.Path.isEmpty()){ QString Path = Item->Data.Path; Path.replace( "\\*", "" ); InputFileBrowserPath->setText( Path ); for ( auto& Session : HavocX::Teamserver.Sessions ) { if ( Session.Name.compare( SessionID ) == 0 ) { TableClear(); Session.InteractedWidget->DemonCommands->Execute.FS( Util::gen_random( 8 ).c_str(), "dir;ui", Path ); } } } } void FileBrowser::onTableMenuRemove() { } void FileBrowser::onTreeMenuListDrives() { } void FileBrowser::onTreeMenuMkdir() { } void FileBrowser::onTreeMenuReload() { } void FileBrowser::onTreeMenuRemove() { } void FileBrowser::onInputPath() { auto Path = InputFileBrowserPath->text(); TableClear(); ChangePathAndSendRequest( Path ); } void FileBrowser::TreeUpdate() { TreeClear( ); for ( auto& Data : DirData ) { auto Split = Data.Path.split( "\\" ); // check if any Dir contains an empty space. if so then remove it. for ( int i = 0; i < Split.size(); i++ ) { if ( Split[ i ].compare( "" ) == 0 ) Split.removeAt( i ); } for ( int i = 0; i < Split.size(); i++ ) { if ( i == 0 ) { TreeAddDisk( Split[ i ] + "\\" ); continue; } auto Parent = JoinAtIndex( Split, i, "\\" ); auto Item = new FileBrowserTreeItem; Item->setText( 0, Split[ i ] ); Item->setIcon( 0, QIcon( ":/icons/FileBrowserFolder" ) ); Item->ParentPath = Parent + Split[ i ] + "\\"; TreeAddChildToParent( Parent, Item ); } for ( auto& subData : Data.Files ) { if ( subData.Type.compare( "dir" ) == 0 ) { auto Path = subData.Path; auto Item = new FileBrowserTreeItem; auto SubPath = subData.Path.replace( "\\\\", "\\" ); if ( ! SubPath.endsWith( '\\' ) ) SubPath = subData.Path + "\\"; auto SubName = subData.Name.replace( "\\\\", "\\" );; if ( ! SubName.endsWith( '\\' ) ) SubName = subData.Name + "\\"; Item->setText( 0, subData.Name ); Item->setIcon( 0, QIcon( ":/icons/FileBrowserFolder" ) ); Item->ParentPath = SubPath + SubName; TreeAddChildToParent( Path, Item ); } } } FileBrowserTree->expandAll(); } void FileBrowser::TreeClear( ) { FileBrowserTree->clear(); } auto FileBrowser::TreeSearchPath( QString ParentPath ) -> FileBrowserTreeItem* { auto Iterator = QTreeWidgetItemIterator( FileBrowserTree ); auto Item = ( ( FileBrowserTreeItem* ) nullptr ); while ( *Iterator ) { Item = ( ( FileBrowserTreeItem* ) ( *Iterator ) ); if ( ( Item->ParentPath.compare( ParentPath ) == 0 ) ) return Item; ++Iterator; } return nullptr; } void FileBrowser::TreeAddDisk( QString Disk ) { if ( ! TreeSearchPath( Disk ) ) { auto DiskItem = new FileBrowserTreeItem; DiskItem->setIcon( 0, QIcon( ":/icons/FileBrowserHardDisk" ) ); DiskItem->setText( 0, Disk ); DiskItem->ParentPath = Disk; FileBrowserTree->addTopLevelItem( DiskItem ); } } void FileBrowser::TreeAddChildToParent( QString ParentPath, FileBrowserTreeItem* DataItem ) { auto Parent = TreeSearchPath( ParentPath ); if ( Parent ) { if ( TreePathExists( DataItem->ParentPath ) ) return; Parent->addChild( DataItem ); return; } } auto FileBrowser::TreePathExists( QString Path ) -> bool { auto Iterator = QTreeWidgetItemIterator( FileBrowserTree ); auto Item = ( ( FileBrowserTreeItem* ) nullptr ); while ( *Iterator ) { Item = ( ( FileBrowserTreeItem* ) ( *Iterator ) ); if ( ( Item->ParentPath.compare( Path ) == 0 ) ) return true; ++Iterator; } return false; }