From ffecc7f721d2626834deecf1b0de895030743acd Mon Sep 17 00:00:00 2001 From: Felix de las Pozas Alvarez Date: Mon, 15 Apr 2019 23:49:31 +0200 Subject: [PATCH] More fine-grained progress report both in the general progress bar and the individual hashes. - Progress report on each hash computation in the assigned table cell. - Global progress report using the windows task bar button. - More fine-grained progress report in both hash checking and computing. --- AboutDialog.cpp | 7 +- AboutDialog.ui | 2 +- CMakeLists.txt | 7 +- ComputerThread.cpp | 100 +++++++++++++---- ComputerThread.h | 158 +++++++++++++++++++-------- Hash.h | 26 +++-- SimpleHasher.cpp | 265 +++++++++++++++++++++++++++++++++++---------- SimpleHasher.h | 91 ++++++++++++++-- hash/SHA1.cpp | 48 ++++---- hash/SHA1.h | 7 +- hash/SHA224.cpp | 22 ++-- hash/SHA224.h | 2 + hash/SHA256.cpp | 22 ++-- hash/SHA256.h | 2 + hash/SHA384.cpp | 55 +++++----- hash/SHA384.h | 8 +- hash/SHA512.cpp | 22 ++-- hash/SHA512.h | 2 + hash/md5.cpp | 46 ++++---- hash/md5.h | 8 +- hash/tiger.cpp | 43 ++++---- hash/tiger.h | 8 +- readme.md | 12 +- 23 files changed, 671 insertions(+), 292 deletions(-) diff --git a/AboutDialog.cpp b/AboutDialog.cpp index 9f93f74..765248c 100644 --- a/AboutDialog.cpp +++ b/AboutDialog.cpp @@ -20,7 +20,10 @@ // Project #include -const QString VERSION = QString("version 1.0.1"); +// Qt +#include + +const QString VERSION = QString("version 1.1.0"); //----------------------------------------------------------------- AboutDialog::AboutDialog(QWidget *parent, Qt::WindowFlags flags) @@ -35,4 +38,6 @@ AboutDialog::AboutDialog(QWidget *parent, Qt::WindowFlags flags) m_compilationDate->setText(tr("Compiled on ") + compilation_date + compilation_time); m_version->setText(VERSION); + + m_qtVersion->setText(tr("version %1.%2.%3").arg(QT_VERSION_MAJOR).arg(QT_VERSION_MINOR).arg(QT_VERSION_PATCH)); } diff --git a/AboutDialog.ui b/AboutDialog.ui index 5352231..2fa4e5c 100644 --- a/AboutDialog.ui +++ b/AboutDialog.ui @@ -216,7 +216,7 @@ Qt Framework - + version 5.9 diff --git a/CMakeLists.txt b/CMakeLists.txt index 38bfded..6171dce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,8 +4,8 @@ cmake_minimum_required (VERSION 2.8.6) # Version Number set (SIMPLE_HASHER_VERSION_MAJOR 1) -set (SIMPLE_HASHER_VERSION_MINOR 0) -set (SIMPLE_HASHER_VERSION_PATCH 1) +set (SIMPLE_HASHER_VERSION_MINOR 1) +set (SIMPLE_HASHER_VERSION_PATCH 0) # Find includes in corresponding build directories set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -14,7 +14,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) # Find the QtWidgets library -find_package(Qt5 COMPONENTS Widgets Multimedia) +find_package(Qt5 COMPONENTS Widgets Multimedia WinExtras) # We need add -DQT_WIDGETS_LIB when using QtWidgets in Qt 5. #add_definitions(${Qt5Widgets_DEFINITIONS}) @@ -79,6 +79,7 @@ set (CORE_SOURCES set(CORE_EXTERNAL_LIBS Qt5::Widgets + Qt5::WinExtras ) add_executable(SimpleHasher ${CORE_SOURCES}) diff --git a/ComputerThread.cpp b/ComputerThread.cpp index 0079411..02959e4 100644 --- a/ComputerThread.cpp +++ b/ComputerThread.cpp @@ -29,7 +29,7 @@ //---------------------------------------------------------------- ComputerThread::ComputerThread(QMap computations, const int threadsNum, QObject *parent) : QThread {parent} -, m_computations{computations} +, m_computations(computations) , m_abort {false} , m_hashNumber {0} , m_progress {0} @@ -59,6 +59,7 @@ QMap ComputerThread::getResults() const void ComputerThread::abort() { m_abort = true; + m_condition.wakeAll(); } //---------------------------------------------------------------- @@ -66,12 +67,6 @@ void ComputerThread::onHashComputed(const QString &filename, const Hash *hash) { QMutexLocker lock(&m_progressMutex); - emit hashComputed(filename, hash); - - ++m_progress; - - emit progress((100*m_progress)/m_hashNumber); - for(auto hashSPtr: m_computations[filename]) { if(hashSPtr.get() == hash) @@ -81,15 +76,28 @@ void ComputerThread::onHashComputed(const QString &filename, const Hash *hash) } } - --m_threadsNum; - m_condition.wakeAll(); + emit hashComputed(filename, hash); +} + +//---------------------------------------------------------------- +void ComputerThread::onProgressSignaled() +{ + QMutexLocker lock(&m_progressMutex); + + if(m_hashNumber > 0) + { + auto progressValue = m_progress * 100; + + std::for_each(m_threads.constBegin(), m_threads.constEnd(), [&progressValue](const std::shared_ptr task) { if(task) progressValue += task->progress();}); + + emit progress(progressValue/m_hashNumber); + } } //---------------------------------------------------------------- void ComputerThread::run() { QString fileErrors; - QList> threads; for(int i = 0; i < m_computations.keys().size() && !m_abort; ++i) { @@ -97,6 +105,16 @@ void ComputerThread::run() for(auto hash: m_computations[filename]) { + // wait if we have reached the maximum number of threads. + if(m_threadsNum == m_maxThreads) + { + m_mutex.lock(); + m_condition.wait(&m_mutex); + m_mutex.unlock(); + } + + if(m_abort) break; + auto file = new QFile{filename}; if(!file->open(QIODevice::ReadOnly) || !file->seek(0)) @@ -108,30 +126,35 @@ void ComputerThread::run() auto runnable = std::make_shared(hash, file); connect(runnable.get(), SIGNAL(hashComputed(const QString &, const Hash *)), this, SLOT(onHashComputed(const QString &, const Hash *))); + connect(runnable.get(), SIGNAL(hashUpdated(const QString &, const Hash *, const int)), this, SIGNAL(hashUpdated(const QString &, const Hash *, const int))); + connect(runnable.get(), SIGNAL(progressed()), this, SLOT(onProgressSignaled())); + connect(runnable.get(), SIGNAL(finished()), this, SLOT(onThreadFinished())); - threads << runnable; - - // wait if we have reached the maximum number of threads. - if(m_threadsNum == m_maxThreads) { - m_mutex.lock(); - m_condition.wait(&m_mutex); - m_mutex.unlock(); - } + QMutexLocker lock(&m_progressMutex); - ++m_threadsNum; + ++m_threadsNum; + m_threads << runnable; + } runnable->start(); } } - QApplication::processEvents(); + while(!m_threads.isEmpty() && !m_abort) + { + m_mutex.lock(); + m_condition.wait(&m_mutex); + m_mutex.unlock(); + } - for(auto thread: threads) + if(m_abort) { - // waits for all threads to finish before ending. - thread->wait(); + QMutexLocker lock(&m_progressMutex); + + std::for_each(m_threads.begin(), m_threads.end(), [](std::shared_ptr thread) { thread->abort(); }); } - threads.clear(); + + QApplication::processEvents(); if(!fileErrors.isEmpty()) { @@ -146,3 +169,32 @@ void ComputerThread::run() dialog.exec(); } } + +//---------------------------------------------------------------- +void ComputerThread::onThreadFinished() +{ + QMutexLocker lock(&m_progressMutex); + + --m_threadsNum; + ++m_progress; + + auto senderThread = qobject_cast(sender()); + if(senderThread) + { + disconnect(senderThread, SIGNAL(hashComputed(const QString &, const Hash *)), this, SLOT(onHashComputed(const QString &, const Hash *))); + disconnect(senderThread, SIGNAL(hashUpdated(const QString &, const Hash *, const int)), this, SIGNAL(hashUpdated(const QString &, const Hash *, const int))); + disconnect(senderThread, SIGNAL(progressed()), this, SLOT(onProgressSignaled())); + disconnect(senderThread, SIGNAL(finished()), this, SLOT(onThreadFinished())); + + for(auto thread: m_threads) + { + if(thread.get() == senderThread) + { + m_threads.removeOne(thread); + break; + } + } + } + + m_condition.wakeAll(); +} diff --git a/ComputerThread.h b/ComputerThread.h index 160471d..189526e 100644 --- a/ComputerThread.h +++ b/ComputerThread.h @@ -31,6 +31,104 @@ // C++ #include +#include + +/** \class HashChecker + * \brief Thread for computing an individual hash. + * + */ +class HashChecker +: public QThread +{ + Q_OBJECT + public: + /** \brief HashChecker class constructor. + * \param[in] hash hash object to update. + * \param[in] file opened QFile object. + * \param[in] parent raw pointer of the object parent of this one. + * + */ + HashChecker(std::shared_ptr hash, QFile *file, QObject *parent = nullptr) + : QThread {parent} + , m_hash {hash} + , m_file {file} + , m_progress{0} + , m_abort {false} + {}; + + /** \brief HashChecker class virtual destructor. + * + */ + ~HashChecker() + { + m_file->close(); + delete m_file; + } + + /** \brief Returns the progress of the hash computation in [0,100]. + * + */ + const int progress() const + { return m_progress; } + + /** \brief Aborts the current hash computation. + * + */ + void abort() + { if(isRunning()) m_abort = true; } + + /** \brief Returns true if aborted and false otherwise. + * + */ + const bool aborted() const + { return m_abort; } + + signals: + void hashComputed(const QString &filename, const Hash *hash); + void hashUpdated(const QString &filename, const Hash *hash, const int value); + void progressed(); + + protected: + void run() + { + m_progress = 0; + m_file->seek(0); + unsigned long long message_length = 0; + const unsigned long long fileSize = m_file->size(); + m_hash->reset(); + + while(fileSize != message_length && !m_abort) + { + int currentProgress = (message_length*100.)/fileSize; + if(currentProgress != m_progress) + { + m_progress = currentProgress; + emit progressed(); + emit hashUpdated(m_file->fileName(), m_hash.get(), m_progress); + } + + auto block = m_file->read(m_hash->blockSize()); + message_length += block.length(); + m_hash->update(block, message_length * m_hash->bitsPerUnit()); + + // last block needs to be processed + if((fileSize == message_length) && (block.size() == m_hash->blockSize())) + { + m_hash->update(QByteArray(), message_length * m_hash->bitsPerUnit()); + } + } + + m_file->close(); + if(!m_abort) emit hashComputed(m_file->fileName(), m_hash.get()); + } + + private: + std::shared_ptr m_hash; /** hash object to update. */ + QFile *m_file; /** opened QFile object. */ + int m_progress; /** computation progress value in [0,100]. */ + bool m_abort; /** true if aborted, false otherwise. */ + +}; /** \class ComputerThread * \brief Class to compute the hashes in a separate thread. @@ -48,7 +146,7 @@ class ComputerThread */ ComputerThread(QMap computations, const int threadsNum, QObject *parent = nullptr); - /** \brief ComputeThread clss virtual destructor. + /** \brief ComputeThread class virtual destructor. * */ virtual ~ComputerThread() @@ -72,8 +170,8 @@ class ComputerThread signals: void progress(int value); - void hashComputed(const QString &filename, const Hash *hash); + void hashUpdated(const QString &filename, const Hash *hash, const int value); private slots: /** \brief Computes progress and emits progress and hashComputed signals. @@ -82,6 +180,16 @@ class ComputerThread */ void onHashComputed(const QString &filename, const Hash *hash); + /** \brief Updates the total progress of the computations and reports it. + * + */ + void onProgressSignaled(); + + /** \brief Removes the finished thread from the thread pool. + * + */ + void onThreadFinished(); + protected: virtual void run(); @@ -96,52 +204,8 @@ class ComputerThread int m_maxThreads; /** max number of threads in the system. */ std::atomic m_threadsNum; /** number of threads currently running. */ QMap m_results; /** computed hashes. */ -}; - -/** \class HashChecker - * \brief Thread for computing an individual hash. - * - */ -class HashChecker -: public QThread -{ - Q_OBJECT - public: - /** \brief HashChecker class constructor. - * \param[in] hash hash object to update. - * \param[in] file opened QFile object. - * \param[in] parent raw pointer of the object parent of this one. - * - */ - HashChecker(std::shared_ptr hash, QFile *file, QObject *parent = nullptr) - : QThread{parent} - , m_hash {hash} - , m_file {file} - {}; - - /** \brief HashChecker class virtual destructor. - * - */ - ~HashChecker() - { - m_file->close(); - delete m_file; - } - - signals: - void hashComputed(const QString &filename, const Hash *hash); - - protected: - void run() - { - m_hash->update(*m_file); - emit hashComputed(m_file->fileName(), m_hash.get()); - } - - private: - std::shared_ptr m_hash; /** hash object to update. */ - QFile *m_file; /** opened QFile object. */ + QList> m_threads; /** list of running threads. */ }; #endif // COMPUTERTHREAD_H_ diff --git a/Hash.h b/Hash.h index ff3543d..7f2fae1 100644 --- a/Hash.h +++ b/Hash.h @@ -36,9 +36,7 @@ using HashList = QList; * \brief Base class that defines the basic hash algorithm methods. */ class Hash -: public QObject { - Q_OBJECT public: /** \brief Hash class constructor. * @@ -51,18 +49,15 @@ class Hash virtual ~Hash() {}; - /** \brief Updates the hash with the contents of the file. - * \param[in] file already opened file. + /** \brief Returns the size in bytes of the blocks that the hash processes. * */ - virtual void update(QFile &file) = 0; + virtual const int blockSize() const = 0; - /** \brief Updated the hash with the contents of the buffer. - * \param[in] buffer data buffer. - * \param[in] message_length length of the message being hashed. + /** \brief Returns the size of the unit the hash works with. I.E. 8 bof byte and 1 for bit. * */ - virtual void update(const QByteArray &buffer, const unsigned long long message_length) = 0; + virtual const int bitsPerUnit() const = 0; /** \brief Returns the hash value as a string. * @@ -74,8 +69,17 @@ class Hash */ virtual const QString name() const = 0; - signals: - void finished(); + /** \brief Resets the hash internal values. + * + */ + virtual void reset() = 0; + + /** \brief Updated the hash with the contents of the buffer. + * \param[in] buffer data buffer. + * \param[in] message_length length of the message being hashed. + * + */ + virtual void update(const QByteArray &buffer, const unsigned long long message_length) = 0; }; #endif // HASH_H_ diff --git a/SimpleHasher.cpp b/SimpleHasher.cpp index 8824514..f6416d9 100644 --- a/SimpleHasher.cpp +++ b/SimpleHasher.cpp @@ -38,8 +38,12 @@ #include #include #include +#include #include #include +#include +#include +#include #include QString SimpleHasher::STATE_MD5 = QString("MD5 Enabled"); @@ -64,13 +68,14 @@ const QString NOT_COMPUTED_YET = QString("Hash not checked yet."); //---------------------------------------------------------------- SimpleHasher::SimpleHasher(const QStringList &files, QWidget *parent, Qt::WindowFlags flags) -: QMainWindow{parent, flags} -, m_mode {files.isEmpty() ? Mode::GENERATE : Mode::CHECK} -, m_files {files} -, m_thread {nullptr} -, m_spaces {true} -, m_oneline {false} -, m_uppercase{false} +: QMainWindow (parent, flags) +, m_mode {files.isEmpty() ? Mode::GENERATE : Mode::CHECK} +, m_files {files} +, m_thread {nullptr} +, m_spaces {true} +, m_oneline {false} +, m_uppercase {false} +, m_taskBarButton{nullptr} { qRegisterMetaType("Hash"); qRegisterMetaType>("Point"); @@ -90,6 +95,7 @@ SimpleHasher::SimpleHasher(const QStringList &files, QWidget *parent, Qt::Window m_hashTable->horizontalHeader()->setSectionsClickable(false); m_hashTable->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter); m_hashTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents); + m_hashTable->setItemDelegate(new HashCellDelegate(m_hashTable)); loadSettings(); @@ -154,6 +160,7 @@ void SimpleHasher::hideProgress() m_hashGroup->setEnabled(true); m_progress->hide(); m_cancel->hide(); + if(m_taskBarButton) m_taskBarButton->progress()->setVisible(false); m_cancel->setEnabled(true); } @@ -163,6 +170,8 @@ void SimpleHasher::showProgress() m_hashGroup->setEnabled(false); m_progress->setValue(0); m_progress->show(); + if(m_taskBarButton) m_taskBarButton->progress()->setVisible(true); + if(m_taskBarButton) m_taskBarButton->progress()->setValue(0); m_cancel->show(); } @@ -243,10 +252,15 @@ void SimpleHasher::onComputePressed() for(auto hash: hashes) { auto column = m_headers.indexOf(hash->name()); - auto item = m_hashTable->item(row, column); + auto item = dynamic_cast(m_hashTable->item(row, column)); + item->setProgress(0); + item->setData(Qt::UserRole+1, false); + item->setBackground(palette().background()); + if(item->text() == NOT_FOUND || (m_hashTable->item(row,0)->toolTip() == FILE_NOT_FOUND)) { toRemove << hash; + item->setBackgroundColor(QColor(200,200,50)); } } @@ -266,6 +280,7 @@ void SimpleHasher::onComputePressed() } } + if(m_thread) onCancelPressed(); if(!computations.empty()) { @@ -273,8 +288,10 @@ void SimpleHasher::onComputePressed() showProgress(); connect(m_thread.get(), SIGNAL(progress(int)), m_progress, SLOT(setValue(int))); + if(m_taskBarButton) connect(m_thread.get(), SIGNAL(progress(int)), m_taskBarButton->progress(), SLOT(setValue(int))); connect(m_thread.get(), SIGNAL(finished()), this, SLOT(onComputationFinished())); connect(m_thread.get(), SIGNAL(hashComputed(const QString &, const Hash *)), this, SLOT(onHashComputed(const QString &, const Hash *)), Qt::DirectConnection); + connect(m_thread.get(), SIGNAL(hashUpdated(const QString &, const Hash *, const int)), this, SLOT(onHashUpdated(const QString &, const Hash *, const int)), Qt::DirectConnection); m_thread->start(); } @@ -283,8 +300,46 @@ void SimpleHasher::onComputePressed() //---------------------------------------------------------------- void SimpleHasher::onCancelPressed() { - m_cancel->setEnabled(false); - m_thread->abort(); + if(m_thread) + { + m_cancel->setEnabled(false); + m_thread->abort(); + m_thread->wait(); + + for(int row = 0; row < m_files.size(); ++row) + { + for(int column = 1; column < m_headers.size(); ++column) + { + auto item = dynamic_cast(m_hashTable->item(row, column)); + if(item) + { + bool ok{false}; + auto value = item->data(Qt::UserRole).toInt(&ok); + item->setProgress(0); + + if(ok && value != 0) + { + if(value < 100) + { + item->setData(Qt::UserRole+1, false); + item->setToolTip(tr("Hash computation cancelled.")); + + if(m_mode == Mode::CHECK) + { + item->setBackgroundColor(QColor{200,50,50}); + } + else + { + item->setBackground(palette().background()); + } + } + } + } + } + } + + m_hashTable->update(); + } } //---------------------------------------------------------------- @@ -462,7 +517,9 @@ void SimpleHasher::onCheckBoxStateChanged() enableSave = true; } - auto item = new QTableWidgetItem{text}; + auto item = new HashCellItem{text}; + item->setProgress(0); + item->setData(Qt::UserRole+1, false); item->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); item->setTextAlignment(Qt::AlignCenter); item->setToolTip(m_mode == Mode::GENERATE ? NOT_COMPUTED_TOOLTIP : NOT_FOUND_TOOLTIP); @@ -481,34 +538,38 @@ void SimpleHasher::onCheckBoxStateChanged() //---------------------------------------------------------------- void SimpleHasher::onComputationFinished() { - disconnect(m_thread.get(), SIGNAL(progress(int)), m_progress, SLOT(setValue(int))); - disconnect(m_thread.get(), SIGNAL(finished()), this, SLOT(onComputationFinished())); - disconnect(m_thread.get(), SIGNAL(hashComputed(const QString &, const Hash *)), this, SLOT(onHashComputed(const QString &, const Hash *))); - - if(m_mode == Mode::GENERATE) + if(m_thread) { - auto results = m_thread->getResults(); + disconnect(m_thread.get(), SIGNAL(progress(int)), m_progress, SLOT(setValue(int))); + if(m_taskBarButton) disconnect(m_thread.get(), SIGNAL(progress(int)), m_taskBarButton->progress(), SLOT(setValue(int))); + disconnect(m_thread.get(), SIGNAL(finished()), this, SLOT(onComputationFinished())); + disconnect(m_thread.get(), SIGNAL(hashComputed(const QString &, const Hash *)), this, SLOT(onHashComputed(const QString &, const Hash *))); - for(int i = 0; i < m_files.size(); ++i) + if(m_mode == Mode::GENERATE) { - for(auto hash: results[m_files.at(i)]) + auto results = m_thread->getResults(); + + for(int i = 0; i < m_files.size(); ++i) { - m_results[m_files.at(i)][hash->name()] = hash; + for(auto hash: results[m_files.at(i)]) + { + m_results[m_files.at(i)][hash->name()] = hash; + } } - } - for(auto list: results.values()) - { - list.clear(); - } + for(auto list: results.values()) + { + list.clear(); + } - m_thread = nullptr; - for(int i = 0; i < m_hashTable->columnCount(); ++i) - { - m_hashTable->resizeColumnToContents(i); - } + m_thread = nullptr; + for(int i = 0; i < m_hashTable->columnCount(); ++i) + { + m_hashTable->resizeColumnToContents(i); + } - m_save->setEnabled(true); + m_save->setEnabled(true); + } } hideProgress(); @@ -591,6 +652,7 @@ void SimpleHasher::onHashComputed(const QString& file, const Hash *hash) auto item = m_hashTable->item(row, column); auto itemHash = item->text().remove('\n').remove(' ').toLower(); auto text = hash->value(); + item->setData(Qt::UserRole, 100); if(m_mode == Mode::GENERATE) { @@ -599,6 +661,8 @@ void SimpleHasher::onHashComputed(const QString& file, const Hash *hash) if(m_uppercase) text = text.toUpper(); item->setText(text); + item->setData(Qt::UserRole+1, true); + item->setToolTip(tr("Hash computed.")); m_hashTable->resizeColumnToContents(column); } @@ -612,11 +676,13 @@ void SimpleHasher::onHashComputed(const QString& file, const Hash *hash) if(itemHash == value) { + item->setData(Qt::UserRole+1, true); item->setBackgroundColor(QColor(50,200,50)); item->setToolTip(tr("Correct Hash.")); } else { + item->setData(Qt::UserRole+1, false); item->setBackgroundColor(QColor(200, 50, 50)); item->setToolTip(tr("Incorrect Hash.")); } @@ -833,7 +899,7 @@ const QString SimpleHasher::guessHash(QFile &file) QString result{"Unknown"}; file.seek(0); - auto data = file.read(150); // a bit more than the largest of the hashes (512 bits/4 char bits = 128). + const auto data = file.readLine(150); // a bit more than the largest of the hashes (512 bits/4 char bits = 128). if(data.length() > 32) { @@ -871,7 +937,7 @@ void SimpleHasher::loadInformation() parameterFiles.detach(); m_files.clear(); - this->blockSignals(true); + blockSignals(true); QList checked; for(auto check: {m_md5, m_sha1, m_sha224, m_sha256, m_sha256, m_sha384, m_sha512, m_tiger}) { @@ -885,85 +951,81 @@ void SimpleHasher::loadInformation() for(auto filename: parameterFiles) { QFile file{filename}; - - if(!file.exists() || !file.open(QIODevice::ReadOnly)) + if(!file.exists() || !file.open(QIODevice::ReadOnly|QIODevice::Text)) { fileErrors += tr("%1 error: %2\n").arg(filename).arg(file.errorString()); continue; } - auto path = QFileInfo{filename}.absoluteDir(); - auto hash = guessHash(file); + const auto hash = guessHash(file); + file.close(); - if(hash == "Unknown") + if(hash.compare("Unknown") == 0) { fileErrors += tr("%1 error: %2\n").arg(filename).arg("Unknown hash"); - file.close(); - continue; } - if (hash == "MD5") + if (hash.compare("MD5") == 0) { m_md5->setChecked(true); parameterHashLengths << 32; } else - if (hash == "SHA-1") + if (hash.compare("SHA-1") == 0) { m_sha1->setChecked(true); parameterHashLengths << 40; } else - if (hash == "SHA-224") + if (hash.compare("SHA-224") == 0) { m_sha224->setChecked(true); parameterHashLengths << 56; } else - if (hash == "SHA-256") + if (hash.compare("SHA-256") == 0) { m_sha256->setChecked(true); parameterHashLengths << 64; } else - if (hash == "SHA-384") + if (hash.compare("SHA-384") == 0) { m_sha384->setChecked(true); parameterHashLengths << 96; } else - if (hash == "SHA-512") + if (hash.compare("SHA-512") == 0) { m_sha512->setChecked(true); parameterHashLengths << 128; } else - if (hash == "Tiger") + if (hash.compare("Tiger") == 0) { m_tiger->setChecked(true); parameterHashLengths << 48; } else - Q_ASSERT(false); + parameterHashLengths << 0; hashNameList << hash; } - this->blockSignals(false); + blockSignals(false); onCheckBoxStateChanged(); for(auto filename: parameterFiles) { QFile file{filename}; - auto path = QFileInfo{filename}.absoluteDir(); - - if(!file.exists() || !file.open(QIODevice::ReadOnly)) + if(!file.exists() || !file.open(QIODevice::ReadOnly|QIODevice::Text) || (hashNameList.at(parameterFiles.indexOf(filename)).compare("Unknown") == 0)) { // reported before. continue; } + const auto path = QFileInfo{filename}.absoluteDir(); QStringList files; int begin = 0; auto data = file.readAll(); @@ -978,10 +1040,7 @@ void SimpleHasher::loadInformation() auto fileName = data.mid(begin, end-begin); - if(path.exists(fileName)) - { - files << path.absoluteFilePath(fileName); - } + files << path.absoluteFilePath(fileName); begin = end; } @@ -994,9 +1053,9 @@ void SimpleHasher::loadInformation() while(!line.isEmpty()) { auto lineParts = QString(line).split(' '); - if(lineParts.size() == 2 && path.exists(lineParts[1])) + if(lineParts.size() == 2) { - files << files << path.absoluteFilePath(lineParts[1]); + files << path.absoluteFilePath(lineParts[1]); } line = file.readLine(); @@ -1147,7 +1206,9 @@ void SimpleHasher::addFilesToTable(const QStringList &files) for(int column = 1; column <= columnCount; ++column) { auto text = (m_mode == Mode::GENERATE) ? NOT_COMPUTED : NOT_FOUND; - auto item = new QTableWidgetItem(text); + auto item = new HashCellItem{text}; + item->setProgress(0); + item->setData(Qt::UserRole+1, false); item->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); item->setTextAlignment(Qt::AlignCenter); item->setToolTip(m_mode == Mode::GENERATE ? NOT_COMPUTED_TOOLTIP : NOT_FOUND_TOOLTIP); @@ -1168,3 +1229,89 @@ void SimpleHasher::addFilesToTable(const QStringList &files) m_removeFile->setEnabled(enabled); m_compute->setEnabled(enabled); } + +//---------------------------------------------------------------- +void SimpleHasher::showEvent(QShowEvent* event) +{ + QMainWindow::showEvent(event); + + m_taskBarButton = new QWinTaskbarButton(this); + m_taskBarButton->setWindow(this->windowHandle()); + m_taskBarButton->progress()->setRange(0,100); + m_taskBarButton->progress()->setVisible(false); + + if(m_thread) + { + m_taskBarButton->progress()->setVisible(true); + connect(m_thread.get(), SIGNAL(progress(int)), m_taskBarButton->progress(), SLOT(setValue(int))); + } +} + +//---------------------------------------------------------------- +void SimpleHasher::closeEvent(QCloseEvent* event) +{ + if(m_thread && m_thread->isRunning()) + { + onCancelPressed(); + } +} + +//---------------------------------------------------------------- +void HashCellDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + bool ok{false}; + auto progressValue = index.data(Qt::UserRole).toInt(&ok); + + if(!ok) + { + QStyledItemDelegate::paint(painter, option, index); + } + else + { + painter->save(); + + QStyleOptionViewItem opt = option; + initStyleOption(&opt, index); + + QBrush brush{QColor{210,210,210}}; + if(progressValue == 0 || progressValue >= 100) + { + brush = opt.backgroundBrush; + + painter->setRenderHint(QPainter::Antialiasing, true); + painter->fillRect(option.rect, brush); + } + else + { + QStyleOptionProgressBar progressBarOption; + progressBarOption.rect = option.rect; + progressBarOption.minimum = 0; + progressBarOption.maximum = 100; + progressBarOption.textAlignment = Qt::AlignCenter; + progressBarOption.progress = progressValue; + progressBarOption.textVisible = false; + + QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter); + + if(progressValue < 50) painter->setPen(Qt::black); + else painter->setPen(Qt::white); + } + + painter->setFont(opt.font); + painter->drawText(option.rect, Qt::AlignCenter, index.data(Qt::DisplayRole).toString()); + + painter->restore(); + } +} + +//---------------------------------------------------------------- +void SimpleHasher::onHashUpdated(const QString& filename, const Hash* hash, const int value) +{ + if(value != 100) + { + auto row = m_files.indexOf(filename); + auto column = m_headers.indexOf(hash->name()); + auto item = dynamic_cast(m_hashTable->item(row, column)); + if(item) item->setProgress(value); + } +} diff --git a/SimpleHasher.h b/SimpleHasher.h index c5a7f46..5a5702c 100644 --- a/SimpleHasher.h +++ b/SimpleHasher.h @@ -23,6 +23,9 @@ // Qt #include "ui_SimpleHasher.h" #include +#include +#include +#include // C++ #include @@ -32,6 +35,9 @@ class ComputerThread; class QPoint; +class QPainter; +class QStyleOptionViewItem; +class QModelItem; /** \class SimpleHasher * \brief Application main window class. @@ -56,6 +62,10 @@ class SimpleHasher */ virtual ~SimpleHasher(); + protected: + virtual void showEvent(QShowEvent *event) override; + virtual void closeEvent(QCloseEvent *event) override; + private slots: /** \brief Shows the about dialog. * @@ -105,6 +115,14 @@ class SimpleHasher */ void onHashComputed(const QString &filename, const Hash *hash); + /** \brief Updates the correspondent item in the table with the progress value. + * \param[in] filename filename of the computed hash. + * \param[in] hash hash object pointer. + * \param[in] value Progress value in [0,100] + * + */ + void onHashUpdated(const QString &filename, const Hash *hash, const int value); + /** \brief Copies the values of the selected hashes to the clipboard. * */ @@ -192,16 +210,69 @@ class SimpleHasher */ void addFilesToTable(const QStringList &files); - Mode m_mode; /** operation mode. */ - QStringList m_files; /** files in the table. */ - std::shared_ptr m_thread; /** computer thread. */ - bool m_spaces; /** true to divide the hashes with spaces. */ - bool m_oneline; /** true to show the long hashes in one line. */ - bool m_uppercase; /** true to show the hashes in uppercase. */ - int m_threadsNum; /** number of simultaneous threads to compute hashes. */ - QMap> m_results; /** maps files -> computed hashes. */ - QStringList m_headers; /** list of column strings, just to avoid computing over and over.. */ - std::shared_ptr m_menu; /** contextual menu for the table. */ + Mode m_mode; /** operation mode. */ + QStringList m_files; /** files in the table. */ + std::shared_ptr m_thread; /** computer thread. */ + bool m_spaces; /** true to divide the hashes with spaces. */ + bool m_oneline; /** true to show the long hashes in one line. */ + bool m_uppercase; /** true to show the hashes in uppercase. */ + int m_threadsNum; /** number of simultaneous threads to compute hashes. */ + QMap> m_results; /** maps files -> computed hashes. */ + QStringList m_headers; /** list of column strings, just to avoid computing over and over.. */ + std::shared_ptr m_menu; /** contextual menu for the table. */ + QWinTaskbarButton *m_taskBarButton; /** task bar button widget. */ +}; + +/** \class HashCellItem + * \brief Custom item for the hash table. + * + */ +class HashCellItem +: public QTableWidgetItem +{ + public: + explicit HashCellItem(int type = Type) + : QTableWidgetItem(type) + {}; + + explicit HashCellItem(const QString &text, int type = Type) + : QTableWidgetItem(text, type) + {}; + + explicit HashCellItem(const QIcon &icon, const QString &text, int type = Type) + : QTableWidgetItem(icon, text, type) + {}; + + inline void setProgress(int value) + { + this->setData(Qt::UserRole, value); + } +}; + +/** \class HashCellDelegate + * \brief Custom item delegate to draw the progress of the hash computation over the item. + * + */ +class HashCellDelegate +: public QStyledItemDelegate +{ + Q_OBJECT + public: + /** \brief HashCellDelegate class constructor. + * \param[in] parent Raw pointer of the widget parent of this delegate. + * + */ + explicit HashCellDelegate(QWidget *parent = nullptr) + : QStyledItemDelegate{parent} + {}; + + /** \brief HashCellDelegate class virtual destructor. + * + */ + virtual ~HashCellDelegate() + {}; + + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; #endif // SIMPLEHASHER_H_ diff --git a/hash/SHA1.cpp b/hash/SHA1.cpp index fad311a..1501d8b 100644 --- a/hash/SHA1.cpp +++ b/hash/SHA1.cpp @@ -20,38 +20,28 @@ // Project #include +// C++ +#include +#include + //---------------------------------------------------------------- SHA1::SHA1() : Hash{} -, SHA1_A{0x67452301} -, SHA1_B{0xEFCDAB89} -, SHA1_C{0x98BADCFE} -, SHA1_D{0x10325476} -, SHA1_E{0xC3D2E1F0} { // initialize chaining variables. + reset(); } //---------------------------------------------------------------- -void SHA1::update(QFile &file) +const int SHA1::blockSize() const { - unsigned long long message_length = 0; - const unsigned long long fileSize = file.size(); - - while(fileSize != message_length) - { - auto block = file.read(64); - message_length += block.length(); - update(block, message_length * 8); - - // last block needs to be processed - if((fileSize == message_length) && (block.size() == 64)) - { - update(QByteArray(), message_length * 8); - } - } + return 64; +} - emit finished(); +//---------------------------------------------------------------- +const int SHA1::bitsPerUnit() const +{ + return 8; } //---------------------------------------------------------------- @@ -66,7 +56,7 @@ void SHA1::update(const QByteArray& buffer, const unsigned long long message_len } QByteArray finalBuffer{64,0}; - memcpy(finalBuffer.data(), buffer.constData(), length); + std::memcpy(finalBuffer.data(), buffer.constData(), length); finalBuffer[length++] = 0x80; // if length < 55 there is space for message length, we process 1 block @@ -74,7 +64,7 @@ void SHA1::update(const QByteArray& buffer, const unsigned long long message_len if (length >= 56) { process_block(reinterpret_cast(finalBuffer.constData())); - memset(finalBuffer.data(), 0x00, 64); + std::memset(finalBuffer.data(), 0x00, 64); } for (int loop = 0; loop < 8; loop++) @@ -175,3 +165,13 @@ void SHA1::process_block(const unsigned char *char_block) SHA1_D += d; SHA1_E += e; } + +//---------------------------------------------------------------- +void SHA1::reset() +{ + SHA1_A = 0x67452301; + SHA1_B = 0xEFCDAB89; + SHA1_C = 0x98BADCFE; + SHA1_D = 0x10325476; + SHA1_E = 0xC3D2E1F0; +} diff --git a/hash/SHA1.h b/hash/SHA1.h index 37dd8f7..dc4605f 100644 --- a/hash/SHA1.h +++ b/hash/SHA1.h @@ -42,15 +42,18 @@ class SHA1 virtual ~SHA1() {}; - virtual void update(QFile &file); + virtual const int blockSize() const; - virtual void update(const QByteArray &buffer, const unsigned long long message_length); + virtual const int bitsPerUnit() const; virtual const QString value() const; virtual const QString name() const { return QString("SHA-1"); } + virtual void reset(); + + virtual void update(const QByteArray &buffer, const unsigned long long message_length); private: /** \brief Updates the hash with the char block passed as argument. * \param[in] char_block data buffer at maximum 64 bytes in size. diff --git a/hash/SHA224.cpp b/hash/SHA224.cpp index 8ba9543..6883cfe 100644 --- a/hash/SHA224.cpp +++ b/hash/SHA224.cpp @@ -36,16 +36,9 @@ static const unsigned long SHA224_CONSTANTS[64] = //---------------------------------------------------------------- SHA224::SHA224() : SHA1{} -, SHA224_A{0xc1059ed8} -, SHA224_B{0x367cd507} -, SHA224_C{0x3070dd17} -, SHA224_D{0xf70e5939} -, SHA224_E{0xffc00b31} -, SHA224_F{0x68581511} -, SHA224_G{0x64f98fa7} -, SHA224_H{0xbefa4fa4} { // initialize chaining variables. + reset(); } //---------------------------------------------------------------- @@ -135,3 +128,16 @@ void SHA224::process_block(const unsigned char *char_block) SHA224_G += g; SHA224_H += h; } + +//---------------------------------------------------------------- +void SHA224::reset() +{ + SHA224_A = 0xc1059ed8; + SHA224_B = 0x367cd507; + SHA224_C = 0x3070dd17; + SHA224_D = 0xf70e5939; + SHA224_E = 0xffc00b31; + SHA224_F = 0x68581511; + SHA224_G = 0x64f98fa7; + SHA224_H = 0xbefa4fa4; +} diff --git a/hash/SHA224.h b/hash/SHA224.h index 1d37f1a..b6493db 100644 --- a/hash/SHA224.h +++ b/hash/SHA224.h @@ -47,6 +47,8 @@ class SHA224 virtual const QString name() const override { return QString("SHA-224"); } + virtual void reset() override; + private: virtual void process_block(const unsigned char *char_block) override; diff --git a/hash/SHA256.cpp b/hash/SHA256.cpp index 890c5ed..a8f60e2 100644 --- a/hash/SHA256.cpp +++ b/hash/SHA256.cpp @@ -35,16 +35,9 @@ static const unsigned long SHA256_CONSTANTS[64] = //---------------------------------------------------------------- SHA256::SHA256() : SHA1{} -, SHA256_A{0x6a09e667} -, SHA256_B{0xbb67ae85} -, SHA256_C{0x3c6ef372} -, SHA256_D{0xa54ff53a} -, SHA256_E{0x510e527f} -, SHA256_F{0x9b05688c} -, SHA256_G{0x1f83d9ab} -, SHA256_H{0x5be0cd19} { // initialize chaining variables. + reset(); } //---------------------------------------------------------------- @@ -136,3 +129,16 @@ void SHA256::process_block(const unsigned char* char_block) SHA256_G += g; SHA256_H += h; } + +//---------------------------------------------------------------- +void SHA256::reset() +{ + SHA256_A = 0x6a09e667; + SHA256_B = 0xbb67ae85; + SHA256_C = 0x3c6ef372; + SHA256_D = 0xa54ff53a; + SHA256_E = 0x510e527f; + SHA256_F = 0x9b05688c; + SHA256_G = 0x1f83d9ab; + SHA256_H = 0x5be0cd19; +} diff --git a/hash/SHA256.h b/hash/SHA256.h index b49d26b..33a303f 100644 --- a/hash/SHA256.h +++ b/hash/SHA256.h @@ -47,6 +47,8 @@ class SHA256 virtual const QString name() const override { return QString("SHA-256"); } + virtual void reset() override; + private: virtual void process_block(const unsigned char *char_block) override; diff --git a/hash/SHA384.cpp b/hash/SHA384.cpp index 078fbc8..5da72fe 100644 --- a/hash/SHA384.cpp +++ b/hash/SHA384.cpp @@ -20,6 +20,9 @@ // Project #include +// C++ +#include + /** SHA-384 Constants */ static const unsigned long long SHA384_CONSTANTS[80] = { @@ -48,38 +51,21 @@ static const unsigned long long SHA384_CONSTANTS[80] = //---------------------------------------------------------------- SHA384::SHA384() : Hash{} -, SHA384_A{0xCBBB9D5DC1059ED8LL} -, SHA384_B{0x629A292A367CD507LL} -, SHA384_C{0x9159015A3070DD17LL} -, SHA384_D{0x152FECD8F70E5939LL} -, SHA384_E{0x67332667FFC00B31LL} -, SHA384_F{0x8EB44A8768581511LL} -, SHA384_G{0xDB0C2E0D64F98FA7LL} -, SHA384_H{0x47B5481DBEFA4FA4LL} { // Initialize chaining variables. + reset(); } //---------------------------------------------------------------- -void SHA384::update(QFile &file) +const int SHA384::blockSize() const { - unsigned long long message_length = 0; - const unsigned long long fileSize = file.size(); - - while(fileSize != message_length) - { - auto block = file.read(128); - message_length += block.length(); - update(block, message_length * 8); - - // last block needs to be processed - if((fileSize == message_length) && (block.size() == 128)) - { - update(QByteArray(), message_length * 8); - } - } + return 128; +} - emit finished(); +//---------------------------------------------------------------- +const int SHA384::bitsPerUnit() const +{ + return 8; } //---------------------------------------------------------------- @@ -94,15 +80,15 @@ void SHA384::update(const QByteArray& buffer, const unsigned long long message_l } QByteArray finalBuffer{128,0}; - memcpy(finalBuffer.data(), buffer.constData(), buffer.length()); + std::memcpy(finalBuffer.data(), buffer.constData(), buffer.length()); finalBuffer[length++] = 0x80; - // if length < 55 there is space for message length, we process 1 block + // if length < 112 there is space for message length, we process 1 block // if not, we need to process two blocks if (length >= 112) { process_block(reinterpret_cast(finalBuffer.constData())); - memset(finalBuffer.data(), 0x00, 128); + std::memset(finalBuffer.data(), 0x00, 128); } for (unsigned int loop = 0; loop < 8; loop++) @@ -204,3 +190,16 @@ void SHA384::process_block(const unsigned char* char_block) SHA384_G += g; SHA384_H += h; } + +//---------------------------------------------------------------- +void SHA384::reset() +{ + SHA384_A = 0xCBBB9D5DC1059ED8LL; + SHA384_B = 0x629A292A367CD507LL; + SHA384_C = 0x9159015A3070DD17LL; + SHA384_D = 0x152FECD8F70E5939LL; + SHA384_E = 0x67332667FFC00B31LL; + SHA384_F = 0x8EB44A8768581511LL; + SHA384_G = 0xDB0C2E0D64F98FA7LL; + SHA384_H = 0x47B5481DBEFA4FA4LL; +} diff --git a/hash/SHA384.h b/hash/SHA384.h index 1c5ac00..bb992bf 100644 --- a/hash/SHA384.h +++ b/hash/SHA384.h @@ -34,15 +34,19 @@ class SHA384 virtual ~SHA384() {}; - virtual void update(QFile &file); + virtual const int blockSize() const; - virtual void update(const QByteArray &buffer, const unsigned long long message_length); + virtual const int bitsPerUnit() const; virtual const QString value() const; virtual const QString name() const { return QString("SHA-384"); } + virtual void reset(); + + virtual void update(const QByteArray &buffer, const unsigned long long message_length); + private: /** \brief Updates the hash with the char block passed as argument. * \param[in] char_block data buffer at maximum 128 bytes in size. diff --git a/hash/SHA512.cpp b/hash/SHA512.cpp index ef544b1..3121c31 100644 --- a/hash/SHA512.cpp +++ b/hash/SHA512.cpp @@ -48,16 +48,9 @@ static const unsigned long long SHA512_CONSTANTS[80] = //---------------------------------------------------------------- SHA512::SHA512() : SHA384{} -, SHA512_A{0x6A09E667F3BCC908LL} -, SHA512_B{0xBB67AE8584CAA73BLL} -, SHA512_C{0x3C6EF372FE94F82BLL} -, SHA512_D{0xA54FF53A5F1D36F1LL} -, SHA512_E{0x510E527FADE682D1LL} -, SHA512_F{0x9B05688C2B3E6C1FLL} -, SHA512_G{0x1F83D9ABFB41BD6BLL} -, SHA512_H{0x5BE0CD19137E2179LL} { // Initialize chaining variables. + reset(); } //---------------------------------------------------------------- @@ -152,3 +145,16 @@ void SHA512::process_block(const unsigned char* char_block) SHA512_G += g; SHA512_H += h; } + +//---------------------------------------------------------------- +void SHA512::reset() +{ + SHA512_A = 0x6A09E667F3BCC908LL; + SHA512_B = 0xBB67AE8584CAA73BLL; + SHA512_C = 0x3C6EF372FE94F82BLL; + SHA512_D = 0xA54FF53A5F1D36F1LL; + SHA512_E = 0x510E527FADE682D1LL; + SHA512_F = 0x9B05688C2B3E6C1FLL; + SHA512_G = 0x1F83D9ABFB41BD6BLL; + SHA512_H = 0x5BE0CD19137E2179LL; +} diff --git a/hash/SHA512.h b/hash/SHA512.h index 6f2da72..693ba83 100644 --- a/hash/SHA512.h +++ b/hash/SHA512.h @@ -47,6 +47,8 @@ class SHA512 virtual const QString name() const override { return QString("SHA-512"); } + virtual void reset() override; + private: virtual void process_block(const unsigned char *char_block) override; diff --git a/hash/md5.cpp b/hash/md5.cpp index 6e7de81..0450c89 100644 --- a/hash/md5.cpp +++ b/hash/md5.cpp @@ -20,8 +20,10 @@ // Project #include +// C++ +#include + // Qt -#include #include /* MD5 table : additive constants, abs(sin(j+1)) 0 =< j =< 63 */ @@ -58,34 +60,21 @@ static const unsigned int MD5_SHIFTS[64] = //---------------------------------------------------------------- MD5::MD5() : Hash{} -, A{0x67452301} -, B{0xefcdab89} -, C{0x98badcfe} -, D{0x10325476} { // initialize chaining variables. + reset(); } //---------------------------------------------------------------- -void MD5::update(QFile &file) +const int MD5::blockSize() const { - unsigned long long message_length = 0; - const unsigned long long fileSize = file.size(); - - while(fileSize != message_length) - { - auto block = file.read(64); - message_length += block.length(); - update(block, message_length * 8); - - // last block needs to be processed - if((fileSize == message_length) && (block.size() == 64)) - { - update(QByteArray(), message_length * 8); - } - } + return 64; +} - emit finished(); +//---------------------------------------------------------------- +const int MD5::bitsPerUnit() const +{ + return 8; } //---------------------------------------------------------------- @@ -100,7 +89,7 @@ void MD5::update(const QByteArray &buffer, const unsigned long long message_leng } QByteArray finalBuffer{64,0}; - memcpy(finalBuffer.data(), buffer.constData(), length); + std::memcpy(finalBuffer.data(), buffer.constData(), length); finalBuffer[length++] = 0x80; /* if length < 55 there is space for message length, we process 1 block */ @@ -108,7 +97,7 @@ void MD5::update(const QByteArray &buffer, const unsigned long long message_leng if (length >= 56) { process_block(reinterpret_cast(finalBuffer.constData())); - memset(finalBuffer.data(), 0x00, 64); + std::memset(finalBuffer.data(), 0x00, 64); } for (int loop = 0; loop < 8; loop++) @@ -222,3 +211,12 @@ void MD5::process_block(const unsigned char *char_block) C += c; D += d; } + +//---------------------------------------------------------------- +void MD5::reset() +{ + A = 0x67452301; + B = 0xefcdab89; + C = 0x98badcfe; + D = 0x10325476; +} diff --git a/hash/md5.h b/hash/md5.h index 54370db..59f4e2e 100644 --- a/hash/md5.h +++ b/hash/md5.h @@ -45,15 +45,19 @@ class MD5 virtual ~MD5() {}; - virtual void update(QFile &file); + virtual const int blockSize() const; - virtual void update(const QByteArray &buffer, const unsigned long long message_length); + virtual const int bitsPerUnit() const; virtual const QString value() const; virtual const QString name() const { return QString("MD5"); } + virtual void reset(); + + virtual void update(const QByteArray &buffer, const unsigned long long message_length); + private: /** \brief Updates the hash with the char block passed as argument. * \param[in] char_block data buffer at maximum 64 bytes in size. diff --git a/hash/tiger.cpp b/hash/tiger.cpp index aab1cfa..4af282d 100644 --- a/hash/tiger.cpp +++ b/hash/tiger.cpp @@ -20,6 +20,9 @@ // Project #include +// C++ +#include + // 512 bits (64 chars) "random value" for the generation of the s-boxes. QString Tiger::RANDOM_VALUE = QString("Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham"); @@ -35,9 +38,7 @@ Tiger::Tiger() : Hash{} { // initialize chaining variables - hash.a = 0x0123456789abcdefULL; - hash.b = 0xfedcba9876543210ULL; - hash.c = 0xf096a5b4c3b2e187ULL; + reset(); if(!TABLE_AVAILABLE) { @@ -54,25 +55,15 @@ Tiger::Tiger() } //---------------------------------------------------------------- -void Tiger::update(QFile &file) +const int Tiger::blockSize() const { - unsigned long long message_length = 0; - const unsigned long long fileSize = file.size(); - - while(fileSize != message_length) - { - auto block = file.read(64); - message_length += block.length(); - update(block, message_length); - - // last block needs to be processed - if((fileSize == message_length) && (block.size() == 64)) - { - update(QByteArray(), message_length); - } - } + return 64; +} - emit finished(); +//---------------------------------------------------------------- +const int Tiger::bitsPerUnit() const +{ + return 1; } //---------------------------------------------------------------- @@ -89,7 +80,7 @@ void Tiger::update(const QByteArray& buffer, const unsigned long long message_le QByteArray finalBuffer{64,0}; // copy the remaining bytes of the message to a temporal block - memcpy(finalBuffer.data(), buffer.constData(), length); + std::memcpy(finalBuffer.data(), buffer.constData(), length); // padding the message finalBuffer[length++] = 0x01; @@ -98,7 +89,7 @@ void Tiger::update(const QByteArray& buffer, const unsigned long long message_le if(length > 56) { process_block(reinterpret_cast(finalBuffer.constData())); - memset(finalBuffer.data(), 0x00, 64); + std::memset(finalBuffer.data(), 0x00, 64); } // insert message length at the end of block @@ -245,3 +236,11 @@ void Tiger::generate_table(const unsigned char *message, const unsigned int pass } } } + +//---------------------------------------------------------------- +void Tiger::reset() +{ + hash.a = 0x0123456789abcdefULL; + hash.b = 0xfedcba9876543210ULL; + hash.c = 0xf096a5b4c3b2e187ULL; +} diff --git a/hash/tiger.h b/hash/tiger.h index 8fe3223..2dc1ca8 100644 --- a/hash/tiger.h +++ b/hash/tiger.h @@ -42,15 +42,19 @@ class Tiger virtual ~Tiger() {}; - virtual void update(QFile &file); + virtual const int blockSize() const; - virtual void update(const QByteArray &buffer, const unsigned long long message_length); + virtual const int bitsPerUnit() const; virtual const QString value() const; virtual const QString name() const { return QString("Tiger"); } + virtual void reset(); + + virtual void update(const QByteArray &buffer, const unsigned long long message_length); + private: /** \brief Updates the hash with the char block passed as argument. * \param[in] char_block data buffer at maximum 64 bytes in size. diff --git a/readme.md b/readme.md index d5ed803..ed94b45 100644 --- a/readme.md +++ b/readme.md @@ -37,7 +37,7 @@ Download and execute the latest installer from the [releases](https://github.com # Screenshots Simple main dialog, showing the progress while computing the hashes of some files. -![maindialog](https://cloud.githubusercontent.com/assets/12167134/15993542/772c63ba-30e9-11e6-9190-eae0761fa95b.jpg) +![maindialog](https://user-images.githubusercontent.com/12167134/56167612-ecaf5900-5fd8-11e9-9a3f-f90cf26c8b86.jpg) When checking hash files passed as a parameter the green means success (hashes match), red indicates errors (hashes don't match) and yellow indicates that the files were not found (so hashes can't be checked). @@ -48,7 +48,7 @@ Configuration dialog ![configuration](https://cloud.githubusercontent.com/assets/12167134/15993540/76f68e16-30e9-11e6-852f-328f1455117a.jpg) # Repository information -**Version**: 1.0.1 +**Version**: 1.1.0 **Status**: finished @@ -58,7 +58,7 @@ Configuration dialog | Language |files |blank |comment |code | |:-----------------------------|--------------:|------------:|-----------------:|-------:| -| C++ | 13 | 463 | 378 | 2039 | -| C/C++ Header | 12 | 199 | 493 | 383 | -| CMake | 1 | 16 | 10 | 60 | -| **Total** | **26** | **678** | **881** |**2482**| +| C++ | 13 | 494 | 395 | 2209 | +| C/C++ Header | 12 | 228 | 535 | 472 | +| CMake | 1 | 16 | 10 | 61 | +| **Total** | **26** | **738** | **940** |**2742**|