mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
cb769c62e5
This comment expands all tabs using an 8-character tab-width. You should ignore this commit when using git blame or use git blame -w. In the early days, I used to use tabs where possible for indentation, since emacs did this automatically. In recent years, I have switched to only using spaces, which means qpdf source code has been a mixture of spaces and tabs. I have avoided cleaning this up because of not wanting gratuitous whitespaces change to cloud the output of git blame, but I changed my mind after discussing with users who view qpdf source code in editors/IDEs that have other tab widths by default and in light of the fact that I am planning to start applying automatic code formatting soon.
165 lines
3.3 KiB
C++
165 lines
3.3 KiB
C++
#include <qpdf/MD5.hh>
|
|
|
|
#include <qpdf/QUtil.hh>
|
|
#include <qpdf/QIntC.hh>
|
|
#include <qpdf/QPDFCryptoProvider.hh>
|
|
|
|
#include <stdio.h>
|
|
#include <memory.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.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()
|
|
{
|
|
init();
|
|
}
|
|
|
|
void MD5::encodeString(char const* str)
|
|
{
|
|
size_t len = strlen(str);
|
|
crypto->MD5_init();
|
|
encodeDataIncrementally(str, len);
|
|
crypto->MD5_finalize();
|
|
}
|
|
|
|
void MD5::appendString(char const* input_string)
|
|
{
|
|
encodeDataIncrementally(input_string, strlen(input_string));
|
|
}
|
|
|
|
void MD5::encodeDataIncrementally(char const* data, size_t len)
|
|
{
|
|
this->crypto->MD5_update(QUtil::unsigned_char_pointer(data), len);
|
|
}
|
|
|
|
void MD5::encodeFile(char const *filename, qpdf_offset_t up_to_offset)
|
|
{
|
|
char buffer[1024];
|
|
|
|
FILE *file = QUtil::safe_fopen(filename, "rb");
|
|
size_t len;
|
|
size_t so_far = 0;
|
|
size_t to_try = 1024;
|
|
size_t up_to_size = 0;
|
|
if (up_to_offset >= 0)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
} 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);
|
|
}
|
|
(void) fclose(file);
|
|
|
|
this->crypto->MD5_finalize();
|
|
}
|
|
|
|
void MD5::digest(Digest result)
|
|
{
|
|
this->crypto->MD5_finalize();
|
|
this->crypto->MD5_digest(result);
|
|
}
|
|
|
|
void MD5::print()
|
|
{
|
|
Digest digest_val;
|
|
digest(digest_val);
|
|
|
|
unsigned int i;
|
|
for (i = 0; i < 16; ++i)
|
|
{
|
|
printf("%02x", digest_val[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
std::string MD5::unparse()
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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
|
|
}
|
|
return result;
|
|
}
|