2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-11-17 18:15:09 +00:00
qpdf/libqpdf/MD5.cc

164 lines
3.2 KiB
C++
Raw Normal View History

2019-11-04 02:22:03 +00:00
#include <qpdf/MD5.hh>
2019-11-04 02:22:03 +00:00
#include <qpdf/QIntC.hh>
#include <qpdf/QPDFCryptoProvider.hh>
#include <qpdf/QUtil.hh>
2019-11-04 02:22:03 +00:00
#include <errno.h>
2019-11-04 02:22:03 +00:00
#include <memory.h>
#include <stdio.h>
2019-11-04 02:22:03 +00:00
#include <stdlib.h>
#include <string.h>
MD5::MD5()
{
init();
}
void
MD5::init()
{
this->crypto = QPDFCryptoProvider::getImpl();
this->crypto->MD5_init();
}
void
MD5::finalize()
{
this->crypto->MD5_finalize();
}
void
MD5::reset()
2019-11-04 02:22:03 +00:00
{
init();
}
void
MD5::encodeString(char const* str)
2019-11-04 02:22:03 +00:00
{
size_t len = strlen(str);
crypto->MD5_init();
encodeDataIncrementally(str, len);
crypto->MD5_finalize();
}
void
MD5::appendString(char const* input_string)
2019-11-04 02:22:03 +00:00
{
encodeDataIncrementally(input_string, strlen(input_string));
}
void
MD5::encodeDataIncrementally(char const* data, size_t len)
2019-11-04 02:22:03 +00:00
{
this->crypto->MD5_update(QUtil::unsigned_char_pointer(data), len);
}
void
MD5::encodeFile(char const* filename, qpdf_offset_t up_to_offset)
2019-11-04 02:22:03 +00:00
{
char buffer[1024];
FILE* file = QUtil::safe_fopen(filename, "rb");
2019-11-04 02:22:03 +00:00
size_t len;
size_t so_far = 0;
size_t to_try = 1024;
size_t up_to_size = 0;
if (up_to_offset >= 0) {
2019-11-04 02:22:03 +00:00
up_to_size = QIntC::to_size(up_to_offset);
}
do {
if ((up_to_offset >= 0) && ((so_far + to_try) > up_to_size)) {
to_try = up_to_size - so_far;
}
len = fread(buffer, 1, to_try, file);
if (len > 0) {
encodeDataIncrementally(buffer, len);
so_far += len;
if ((up_to_offset >= 0) && (so_far >= up_to_size)) {
break;
}
}
2019-11-04 02:22:03 +00:00
} while (len > 0);
if (ferror(file)) {
// Assume, perhaps incorrectly, that errno was set by the
// underlying call to read....
(void)fclose(file);
QUtil::throw_system_error(
std::string("MD5: read error on ") + filename);
2019-11-04 02:22:03 +00:00
}
(void)fclose(file);
2019-11-04 02:22:03 +00:00
this->crypto->MD5_finalize();
}
void
MD5::digest(Digest result)
2019-11-04 02:22:03 +00:00
{
this->crypto->MD5_finalize();
this->crypto->MD5_digest(result);
}
void
MD5::print()
2019-11-04 02:22:03 +00:00
{
Digest digest_val;
digest(digest_val);
unsigned int i;
for (i = 0; i < 16; ++i) {
printf("%02x", digest_val[i]);
2019-11-04 02:22:03 +00:00
}
printf("\n");
}
std::string
MD5::unparse()
2019-11-04 02:22:03 +00:00
{
this->crypto->MD5_finalize();
Digest digest_val;
digest(digest_val);
return QUtil::hex_encode(
std::string(reinterpret_cast<char*>(digest_val), 16));
}
std::string
MD5::getDataChecksum(char const* buf, size_t len)
{
MD5 m;
m.encodeDataIncrementally(buf, len);
return m.unparse();
}
std::string
MD5::getFileChecksum(char const* filename, qpdf_offset_t up_to_offset)
{
MD5 m;
m.encodeFile(filename, up_to_offset);
return m.unparse();
}
bool
MD5::checkDataChecksum(char const* const checksum, char const* buf, size_t len)
2019-11-04 02:22:03 +00:00
{
std::string actual_checksum = getDataChecksum(buf, len);
return (checksum == actual_checksum);
}
bool
MD5::checkFileChecksum(
char const* const checksum,
char const* filename,
qpdf_offset_t up_to_offset)
2019-11-04 02:22:03 +00:00
{
bool result = false;
try {
std::string actual_checksum = getFileChecksum(filename, up_to_offset);
result = (checksum == actual_checksum);
} catch (std::runtime_error const&) {
// Ignore -- return false
2019-11-04 02:22:03 +00:00
}
return result;
}