diff --git a/ChangeLog b/ChangeLog index 7f4d64f7..308779fd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,9 @@ 2013-01-25 Jay Berkenbilt + * New method QUtil::hex_encode to encode binary data as a + hexadecimal string + * qpdf --check was exiting with status 0 in some rare cases even when errors were found. It now always exits with one of the document error codes (0 for success, 2 for errors, 3 or warnings). diff --git a/examples/pdf-parse-content.cc b/examples/pdf-parse-content.cc index 430c0a06..29a989e7 100644 --- a/examples/pdf-parse-content.cc +++ b/examples/pdf-parse-content.cc @@ -33,15 +33,7 @@ ParserCallbacks::handleObject(QPDFObjectHandle obj) std::cout << obj.getTypeName() << ": "; if (obj.isInlineImage()) { - std::string val = obj.getInlineImageValue(); - char buf[3]; - buf[2] = '\0'; - for (size_t i = 0; i < val.length(); ++i) - { - sprintf(buf, "%02x", (unsigned char)(val[i])); - std::cout << buf; - } - std::cout << std::endl; + std::cout << QUtil::hex_encode(obj.getInlineImageValue()) << std::endl; } else { diff --git a/include/qpdf/QUtil.hh b/include/qpdf/QUtil.hh index ddba97de..9639917d 100644 --- a/include/qpdf/QUtil.hh +++ b/include/qpdf/QUtil.hh @@ -56,6 +56,12 @@ namespace QUtil QPDF_DLL char* copy_string(std::string const&); + // Returns lower-case hex-encoded version of the string, treating + // each character in the input string as unsigned. The output + // string will be twice as long as the input string. + QPDF_DLL + std::string hex_encode(std::string const&); + // Set stdin, stdout to binary mode QPDF_DLL void binary_stdout(); diff --git a/libqpdf/MD5.cc b/libqpdf/MD5.cc index 70be696d..57bcc45f 100644 --- a/libqpdf/MD5.cc +++ b/libqpdf/MD5.cc @@ -386,16 +386,7 @@ void MD5::print() std::string MD5::unparse() { final(); - - char result[33]; - char* p = result; - unsigned int i; - for (i = 0; i < 16; ++i) - { - sprintf(p, "%02x", digest_val[i]); - p += 2; - } - return result; + return QUtil::hex_encode(std::string((char*)digest_val, 16)); } std::string diff --git a/libqpdf/Pl_SHA2.cc b/libqpdf/Pl_SHA2.cc index 018f411f..84f24d6e 100644 --- a/libqpdf/Pl_SHA2.cc +++ b/libqpdf/Pl_SHA2.cc @@ -2,6 +2,7 @@ #include #include #include +#include Pl_SHA2::Pl_SHA2(int bits, Pipeline* next) : Pipeline("sha2", next), @@ -150,15 +151,5 @@ Pl_SHA2::getHexDigest() throw std::logic_error( "digest requested for in-progress SHA2 Pipeline"); } - std::string raw = getRawDigest(); - size_t raw_size = raw.length(); - size_t hex_size = 1 + (2 * raw_size); - PointerHolder bufp(true, new char[hex_size]); - char* buf = bufp.getPointer(); - buf[hex_size - 1] = '\0'; - for (unsigned int i = 0; i < raw_size; ++i) - { - std::sprintf(buf + i * 2, "%02x", (unsigned char)raw[i]); - } - return buf; + return QUtil::hex_encode(getRawDigest()); } diff --git a/libqpdf/QPDF_Name.cc b/libqpdf/QPDF_Name.cc index 19610bff..9adb25b5 100644 --- a/libqpdf/QPDF_Name.cc +++ b/libqpdf/QPDF_Name.cc @@ -2,6 +2,7 @@ #include #include +#include QPDF_Name::QPDF_Name(std::string const& name) : name(name) @@ -16,7 +17,6 @@ std::string QPDF_Name::normalizeName(std::string const& name) { std::string result; - char num[4]; result += name[0]; for (unsigned int i = 1; i < name.length(); ++i) { @@ -24,8 +24,7 @@ QPDF_Name::normalizeName(std::string const& name) // Don't use locale/ctype here; follow PDF spec guidelines. if (strchr("#()<>[]{}/%", ch) || (ch < 33) || (ch > 126)) { - sprintf(num, "#%02x", (unsigned char) ch); - result += num; + result += "#" + QUtil::hex_encode(std::string(&ch, 1)); } else { diff --git a/libqpdf/QPDF_String.cc b/libqpdf/QPDF_String.cc index 3a8e7074..619adef6 100644 --- a/libqpdf/QPDF_String.cc +++ b/libqpdf/QPDF_String.cc @@ -90,14 +90,7 @@ QPDF_String::unparse(bool force_binary) std::string result; if (use_hexstring) { - result += "<"; - char num[3]; - for (unsigned int i = 0; i < this->val.length(); ++i) - { - sprintf(num, "%02x", (unsigned char) this->val[i]); - result += num; - } - result += ">"; + result += "<" + QUtil::hex_encode(this->val) + ">"; } else { diff --git a/libqpdf/QUtil.cc b/libqpdf/QUtil.cc index 3cdfdc49..faccaee7 100644 --- a/libqpdf/QUtil.cc +++ b/libqpdf/QUtil.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -163,6 +164,21 @@ QUtil::copy_string(std::string const& str) return result; } +std::string +QUtil::hex_encode(std::string const& input) +{ + size_t input_size = input.length(); + size_t hex_size = 1 + (2 * input_size); + PointerHolder bufp(true, new char[hex_size]); + char* buf = bufp.getPointer(); + buf[hex_size - 1] = '\0'; + for (unsigned int i = 0; i < input_size; ++i) + { + sprintf(buf + i * 2, "%02x", (unsigned char)input[i]); + } + return buf; +} + void QUtil::binary_stdout() { diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index d6534abf..a1a467b8 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -75,16 +75,9 @@ ParserCallbacks::handleObject(QPDFObjectHandle obj) std::cout << obj.getTypeName() << ": "; if (obj.isInlineImage()) { + // Exercise getTypeCode assert(obj.getTypeCode() == QPDFObject::ot_inlineimage); - std::string val = obj.getInlineImageValue(); - char buf[3]; - buf[2] = '\0'; - for (size_t i = 0; i < val.length(); ++i) - { - sprintf(buf, "%02x", (unsigned char)(val[i])); - std::cout << buf; - } - std::cout << std::endl; + std::cout << QUtil::hex_encode(obj.getInlineImageValue()) << std::endl; } else {