154 lines
4.4 KiB
C++
154 lines
4.4 KiB
C++
|
|
#include "hash.h"
|
|
|
|
#include "globals/db_names.h"
|
|
|
|
#include "utilities/checks.h"
|
|
#include "utilities/gzip.h"
|
|
#include "utilities/io.h"
|
|
#include "utilities/vectors.h"
|
|
|
|
#include "modules/dialogs.h"
|
|
#include "modules/exceptions.h"
|
|
|
|
#include "modules/database/database.h"
|
|
|
|
#include "sha256.h"
|
|
|
|
#include <ios>
|
|
|
|
#include <QVariant>
|
|
|
|
|
|
void HashOps::setDialogLevel( const DialogsLevel new_level ) noexcept
|
|
{
|
|
this->dialogs_level = new_level;
|
|
}
|
|
|
|
|
|
// reads the database holding the already used hashes
|
|
bool HashOps::loadUsedHashesLists( const std::string& db_path ) noexcept
|
|
{
|
|
DatabaseWrapper db{ DatabaseHandler::get( DatabaseType::Hashes ) };
|
|
|
|
db.open( db_path, this->dialogs_level==DL_EXPLANATORY );
|
|
|
|
const QString stmt{ QStringLiteral(R"(SELECT "hash" FROM "%1";)") };
|
|
|
|
for ( const auto& [wid,name] : this->ws_names ) {
|
|
|
|
QueryWrapper query{ db.getQuery() };
|
|
|
|
query( stmt.arg( name ) );
|
|
|
|
while ( query->next() ) {
|
|
const QString hash{ query[0].toString() };
|
|
if ( hash.size() != 64ul ) {
|
|
// not a valid sha256 hash
|
|
continue;
|
|
}
|
|
this->hashes.at( wid ).push_back( hash.toStdString() );
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// returns the hash
|
|
void HashOps::digestFile( const std::string& file_path, std::string& hash )
|
|
{
|
|
std::string content;
|
|
try {
|
|
try {
|
|
// try reading as gzip compressed file
|
|
GZutils::readFile( file_path, content );
|
|
|
|
} catch ( const GenericException& ) {
|
|
// failed closing file pointer
|
|
throw;
|
|
|
|
} catch (...) {
|
|
// failed as gzip, try as text file
|
|
if ( ! content.empty() ) {
|
|
content.clear();
|
|
}
|
|
IOutils::readFile( file_path, content );
|
|
}
|
|
|
|
// re-catched in craplog
|
|
} catch ( const GenericException& ) {
|
|
// failed closing gzip file pointer
|
|
throw GenericException( QStringLiteral("%1:\n%2").arg(
|
|
DialogSec::tr("An error occured while reading the gzipped file"),
|
|
QString::fromStdString( file_path )
|
|
).toStdString() );
|
|
|
|
} catch ( const std::ios_base::failure& ) {
|
|
// failed reading as text
|
|
throw GenericException( QStringLiteral("%1:\n%2").arg(
|
|
DialogSec::tr("An error occured while reading the file"),
|
|
QString::fromStdString( file_path )
|
|
).toStdString() );
|
|
|
|
} catch (...) {
|
|
// failed somehow
|
|
throw GenericException( QStringLiteral("%1:\n%2").arg(
|
|
DialogSec::tr("Something failed while handling the file"),
|
|
QString::fromStdString( file_path )
|
|
).toStdString() );
|
|
}
|
|
|
|
SHA256 sha;
|
|
sha.update( content );
|
|
uint8_t* digest{ sha.digest() };
|
|
// return the hex digest
|
|
hash.append( SHA256::toString(digest) );
|
|
delete digest;
|
|
}
|
|
|
|
|
|
// check if the given hash is from a file which has been used already
|
|
bool HashOps::hasBeenUsed( const std::string &file_hash, const WebServer& web_server) const noexcept
|
|
{
|
|
const auto& ws_hashes{ this->hashes.at( web_server ) };
|
|
return std::any_of(
|
|
ws_hashes.cbegin(), ws_hashes.cend(),
|
|
[&file_hash]( const std::string& hash )
|
|
{ return file_hash == hash; } );
|
|
}
|
|
|
|
|
|
void HashOps::insertUsedHashes( const std::string& db_path, const std::vector<std::string>& hashes, const WebServer& web_server )
|
|
{
|
|
const bool explain_msg{ this->dialogs_level > DL_ESSENTIAL };
|
|
const bool explain_err{ this->dialogs_level == DL_EXPLANATORY };
|
|
|
|
DatabaseWrapper db{ DatabaseHandler::get( DatabaseType::Hashes ) };
|
|
|
|
db.open( db_path, explain_err );
|
|
|
|
db.startTransaction( explain_msg, explain_err );
|
|
|
|
try {
|
|
|
|
for ( const std::string& hash : hashes ) {
|
|
|
|
if ( ! VecOps::contains( this->hashes.at( web_server ), hash ) ) {
|
|
|
|
db.getQuery()( QStringLiteral(R"(INSERT INTO "%1" ( hash ) VALUES ( '%2' );)")
|
|
.arg( this->ws_names.at(web_server), QString::fromStdString(hash).replace(QLatin1Char('\''),QLatin1String("''")) ) );
|
|
}
|
|
}
|
|
|
|
db.commitTransaction( explain_msg, explain_err );
|
|
|
|
auto& used_hashes{ this->hashes.at( web_server ) };
|
|
used_hashes.insert( used_hashes.end(), hashes.begin(), hashes.end() );
|
|
|
|
} catch (...) {
|
|
// rollback the transaction
|
|
db.rollbackTransaction( explain_msg, explain_err );
|
|
}
|
|
}
|