diff --git a/GCryptCLI/include/DataIngestionLayer.h b/GCryptCLI/include/DataIngestionLayer.h index 871688f..e8a8ab2 100644 --- a/GCryptCLI/include/DataIngestionLayer.h +++ b/GCryptCLI/include/DataIngestionLayer.h @@ -35,6 +35,9 @@ namespace IO { //! Returns true, if EOF is reached, and there are no more blocks to fetch (GetNextBlock()) static bool IsFinished(); + //! Returns how many blocks have been read, in total + static std::size_t NBlocksRead(); + private: static std::istream* in; @@ -57,6 +60,9 @@ namespace IO { // Are we reading ciphertext or regular text? static bool isReadingCiphertext; + // How many blocks have been read in total + static std::size_t nBlocksRead; + // All read blocks, that haven't been given out yet static std::queue blocks; diff --git a/GCryptCLI/include/ProgressPrinter.h b/GCryptCLI/include/ProgressPrinter.h new file mode 100644 index 0000000..6b23c8b --- /dev/null +++ b/GCryptCLI/include/ProgressPrinter.h @@ -0,0 +1,23 @@ +#ifndef GCRYPTCLI_PROGRESSPRINTER_H +#define GCRYPTCLI_PROGRESSPRINTER_H + +#include +#include "CommandlineInterface.h" + +// This class has the task to output progress to stderr, if requested +class ProgressPrinter { + public: + //! Will print progress to stderr, if requested, and the interval matches + static void PrintIfAppropriate( + const std::string& message, + const std::size_t current, + const std::size_t target + ); + + private: + // No instanciation! >:( + ProgressPrinter() {}; +}; + +#endif + diff --git a/GCryptCLI/include/Version.h b/GCryptCLI/include/Version.h index fd29be3..5b9f81f 100644 --- a/GCryptCLI/include/Version.h +++ b/GCryptCLI/include/Version.h @@ -1,7 +1,7 @@ #ifndef GCRYPTCLI_VERSION_H #define GCRYPTCLI_VERSION_H -#define GCRYPTCLI_VERSION 0.125 +#define GCRYPTCLI_VERSION 0.1251 #endif diff --git a/GCryptCLI/src/CommandlineInterface.cpp b/GCryptCLI/src/CommandlineInterface.cpp index 14936d9..72db0df 100644 --- a/GCryptCLI/src/CommandlineInterface.cpp +++ b/GCryptCLI/src/CommandlineInterface.cpp @@ -64,10 +64,13 @@ void CommandlineInterface::Init(int argc, const char* const* argv) { nupp.RegisterConstraint("--keyask", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--key", "--keyfile", "--hash" })); nupp.RegisterAbbreviation("-ka", "--keyask"); - nupp.RegisterDescription("--progress", "Print digestion progress to stdout. May be advisable for large files, as the cipher is rather slow."); + nupp.RegisterDescription("--progress", "Print digestion progress to stderr. May be advisable for large files, as the cipher is rather slow."); nupp.RegisterConstraint("--progress", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {})); nupp.RegisterAbbreviation("-p", "--progress"); + nupp.RegisterDescription("--progress-interval", "Print digestion progress reports every these many blocks."); + nupp.RegisterConstraint("--progress-interval", ParamConstraint(true, DATA_TYPE::INT, { "1000" }, true, {})); + nupp.RegisterDescription("--iobase-bytes", "Interpret and output ciphertexts as raw bytes."); nupp.RegisterConstraint("--iobase-bytes", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-2", "--iobase-8", "--iobase-10", "--iobase-16", "--iobase-64", "--iobase-uwu", "--iobase-ugh" })); @@ -168,6 +171,14 @@ void CommandlineInterface::SpecialCompatibilityChecking() { CrashWithMsg("Length of --keyfile is zero! That can't be a valid path!"); } + if ( + (nupp.HasParam("--progress")) && + (!nupp.HasParam("--puffer-input")) + + ) { + CrashWithMsg("--progress requires --puffer-input to work!"); + } + return; } diff --git a/GCryptCLI/src/DataIngestionLayer.cpp b/GCryptCLI/src/DataIngestionLayer.cpp index 781b796..96c1991 100644 --- a/GCryptCLI/src/DataIngestionLayer.cpp +++ b/GCryptCLI/src/DataIngestionLayer.cpp @@ -68,6 +68,7 @@ void DataIngestionLayer::Init() { initialized = true; reachedEof = false; + nBlocksRead = 0; return; } @@ -142,6 +143,7 @@ void DataIngestionLayer::ReadBlock() { } blocks.emplace(newBlock); + nBlocksRead++; break; } @@ -247,6 +249,7 @@ void DataIngestionLayer::ReadBlock() { // Enqueue it to be processed by some module blocks.emplace(newBlock); + nBlocksRead++; foundBlock = true; // Now we have to calculate how many bytes we've read TOO MANY. @@ -351,11 +354,16 @@ Block DataIngestionLayer::GetNextBlock() { return popped; } +std::size_t DataIngestionLayer::NBlocksRead() { + return nBlocksRead; +} + std::istream* DataIngestionLayer::in; std::ifstream DataIngestionLayer::ifs; std::istringstream DataIngestionLayer::iss; bool DataIngestionLayer::reachedEof = false; bool DataIngestionLayer::initialized = false; bool DataIngestionLayer::isReadingCiphertext; +std::size_t DataIngestionLayer::nBlocksRead = 0; std::queue DataIngestionLayer::blocks; diff --git a/GCryptCLI/src/ModuleDecryption.cpp b/GCryptCLI/src/ModuleDecryption.cpp index 8d0d963..cf51487 100644 --- a/GCryptCLI/src/ModuleDecryption.cpp +++ b/GCryptCLI/src/ModuleDecryption.cpp @@ -1,6 +1,7 @@ #include "ModuleDecryption.h" #include "DataIngestionLayer.h" #include "DataOutputLayer.h" +#include "ProgressPrinter.h" #include "KeyManager.h" #include @@ -21,6 +22,7 @@ void Decryption::Run() { GCipher::DIRECTION::DECIPHER ); + std::size_t nBlocksDigested = 0; while (!IO::DataOutputLayer::IsFinished()) { // Read in new blocks, if not reached eof if (!IO::DataIngestionLayer::ReachedEOF()) { @@ -29,8 +31,17 @@ void Decryption::Run() { // Process a block, if one is ready if (IO::DataIngestionLayer::IsBlockReady()) { + + // Print progress, if appropriate + ProgressPrinter::PrintIfAppropriate( + "Decrypting", + nBlocksDigested, + IO::DataIngestionLayer::NBlocksRead() + ); + const Block cleartext = IO::DataIngestionLayer::GetNextBlock(); const Block ciphertext = cipher.Digest(cleartext); + nBlocksDigested++; // Enqueue the block for output IO::DataOutputLayer::Enqueue(ciphertext); diff --git a/GCryptCLI/src/ModuleEncryption.cpp b/GCryptCLI/src/ModuleEncryption.cpp index c0fe11d..b902f42 100644 --- a/GCryptCLI/src/ModuleEncryption.cpp +++ b/GCryptCLI/src/ModuleEncryption.cpp @@ -2,7 +2,9 @@ #include "DataIngestionLayer.h" #include "DataOutputLayer.h" #include "KeyManager.h" +#include "ProgressPrinter.h" #include +#include using namespace Module; using namespace Leonetienne::GCrypt; @@ -21,6 +23,7 @@ void Encryption::Run() { GCipher::DIRECTION::ENCIPHER ); + std::size_t nBlocksDigested = 0; while (!IO::DataOutputLayer::IsFinished()) { // Read in new blocks, if not reached eof if (!IO::DataIngestionLayer::ReachedEOF()) { @@ -29,8 +32,17 @@ void Encryption::Run() { // Process a block, if one is ready if (IO::DataIngestionLayer::IsBlockReady()) { + + // Print progress, if appropriate + ProgressPrinter::PrintIfAppropriate( + "Encrypting", + nBlocksDigested, + IO::DataIngestionLayer::NBlocksRead() + ); + const Block cleartext = IO::DataIngestionLayer::GetNextBlock(); const Block ciphertext = cipher.Digest(cleartext); + nBlocksDigested++; // Enqueue the block for output IO::DataOutputLayer::Enqueue(ciphertext); diff --git a/GCryptCLI/src/ModuleHashing.cpp b/GCryptCLI/src/ModuleHashing.cpp index 4f88ba2..f1c613f 100644 --- a/GCryptCLI/src/ModuleHashing.cpp +++ b/GCryptCLI/src/ModuleHashing.cpp @@ -1,6 +1,7 @@ #include "ModuleHashing.h" #include "DataIngestionLayer.h" #include "DataOutputLayer.h" +#include "ProgressPrinter.h" #include "KeyManager.h" #include @@ -19,6 +20,7 @@ void Hashing::Run() { GHash hasher; // Read in new blocks, if not reached eof + std::size_t nBlocksDigested = 0; while (!IO::DataIngestionLayer::IsFinished()) { if (!IO::DataIngestionLayer::ReachedEOF()) { IO::DataIngestionLayer::ReadBlock(); @@ -26,8 +28,17 @@ void Hashing::Run() { // Process a block, if one is ready if (IO::DataIngestionLayer::IsBlockReady()) { + + // Print progress, if appropriate + ProgressPrinter::PrintIfAppropriate( + "Hashing", + nBlocksDigested, + IO::DataIngestionLayer::NBlocksRead() + ); + const Block cleartext = IO::DataIngestionLayer::GetNextBlock(); hasher.Digest(cleartext); + nBlocksDigested++; } } diff --git a/GCryptCLI/src/ProgressPrinter.cpp b/GCryptCLI/src/ProgressPrinter.cpp new file mode 100644 index 0000000..f6ea1ad --- /dev/null +++ b/GCryptCLI/src/ProgressPrinter.cpp @@ -0,0 +1,28 @@ +#include "ProgressPrinter.h" +#include "CommandlineInterface.h" +#include + +void ProgressPrinter::PrintIfAppropriate( + const std::string& message, + const std::size_t current, + const std::size_t target +) { + if ( + (CommandlineInterface::Get().HasParam("--progress")) && + (current % CommandlineInterface::Get()["--progress-interval"].GetInt32() == 0) + ) { + std::cerr + << message + << "... (Block " + << current + 1 + << " / " + << target + << " - " << ((float)(current+1)*100 / target) + << "%)" + << std::endl + ; + } + + return; +} +