file(DOWNLOAD): Generalize EXPECTED_MD5 to EXPECTED_HASH

Add support for SHA algorithms.
This commit is contained in:
Bill Hoffman 2012-08-21 18:41:24 -04:00 committed by Brad King
parent 2da17ef797
commit 34567dfc0d
3 changed files with 111 additions and 39 deletions

View File

@ -10,6 +10,7 @@
See the License for more information. See the License for more information.
============================================================================*/ ============================================================================*/
#include "cmFileCommand.h" #include "cmFileCommand.h"
#include "cmCryptoHash.h"
#include "cmake.h" #include "cmake.h"
#include "cmHexFileConverter.h" #include "cmHexFileConverter.h"
#include "cmInstallType.h" #include "cmInstallType.h"
@ -2666,7 +2667,9 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
long inactivity_timeout = 0; long inactivity_timeout = 0;
std::string verboseLog; std::string verboseLog;
std::string statusVar; std::string statusVar;
std::string expectedMD5sum; std::string expectedHash;
std::string hashMatchMSG;
cmsys::auto_ptr<cmCryptoHash> hash;
bool showProgress = false; bool showProgress = false;
while(i != args.end()) while(i != args.end())
@ -2725,48 +2728,67 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
this->SetError("DOWNLOAD missing sum value for EXPECTED_MD5."); this->SetError("DOWNLOAD missing sum value for EXPECTED_MD5.");
return false; return false;
} }
expectedMD5sum = cmSystemTools::LowerCase(*i); hash = cmsys::auto_ptr<cmCryptoHash>(cmCryptoHash::New("MD5"));
hashMatchMSG = "MD5 sum";
expectedHash = cmSystemTools::LowerCase(*i);
} }
else if(*i == "SHOW_PROGRESS") else if(*i == "SHOW_PROGRESS")
{ {
showProgress = true; showProgress = true;
} }
else if(*i == "EXPECTED_HASH")
{
++i;
if(i != args.end())
{
hash = cmsys::auto_ptr<cmCryptoHash>(cmCryptoHash::New(i->c_str()));
if(!hash.get())
{
std::string err = "DOWNLOAD bad SHA type: ";
err += *i;
this->SetError(err.c_str());
return false;
}
hashMatchMSG = *i;
hashMatchMSG += " hash";
++i;
}
if(i != args.end())
{
expectedHash = cmSystemTools::LowerCase(*i);
}
else
{
this->SetError("DOWNLOAD missing time for EXPECTED_HASH.");
return false;
}
}
++i; ++i;
} }
// If file exists already, and caller specified an expected md5 or sha,
// If file exists already, and caller specified an expected md5 sum, // and the existing file already has the expected hash, then simply
// and the existing file already has the expected md5 sum, then simply
// return. // return.
// //
if(cmSystemTools::FileExists(file.c_str()) && if(cmSystemTools::FileExists(file.c_str()) && hash.get())
!expectedMD5sum.empty())
{ {
char computedMD5[32]; std::string msg;
std::string actualHash = hash->HashFile(file.c_str());
if (!cmSystemTools::ComputeFileMD5(file.c_str(), computedMD5)) if(actualHash == expectedHash)
{
this->SetError("DOWNLOAD cannot compute MD5 sum on pre-existing file");
return false;
}
std::string actualMD5sum = cmSystemTools::LowerCase(
std::string(computedMD5, 32));
if (expectedMD5sum == actualMD5sum)
{ {
msg = "returning early; file already exists with expected ";
msg += hashMatchMSG;
msg += "\"";
if(statusVar.size()) if(statusVar.size())
{ {
cmOStringStream result; cmOStringStream result;
result << (int)0 << ";\"" result << (int)0 << ";\"" << msg;
"returning early: file already exists with expected MD5 sum\"";
this->Makefile->AddDefinition(statusVar.c_str(), this->Makefile->AddDefinition(statusVar.c_str(),
result.str().c_str()); result.str().c_str());
} }
return true; return true;
} }
} }
// Make sure parent directory exists so we can write to the file // Make sure parent directory exists so we can write to the file
// as we receive downloaded bits from curl... // as we receive downloaded bits from curl...
// //
@ -2798,7 +2820,6 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
} }
cURLEasyGuard g_curl(curl); cURLEasyGuard g_curl(curl);
::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
check_curl_result(res, "DOWNLOAD cannot set url: "); check_curl_result(res, "DOWNLOAD cannot set url: ");
@ -2888,26 +2909,22 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
// Verify MD5 sum if requested: // Verify MD5 sum if requested:
// //
if (!expectedMD5sum.empty()) if (hash.get())
{ {
char computedMD5[32]; std::string actualHash = hash->HashFile(file.c_str());
if (actualHash.size() == 0)
if (!cmSystemTools::ComputeFileMD5(file.c_str(), computedMD5))
{ {
this->SetError("DOWNLOAD cannot compute MD5 sum on downloaded file"); this->SetError("DOWNLOAD cannot compute hash on downloaded file");
return false; return false;
} }
std::string actualMD5sum = cmSystemTools::LowerCase( if (expectedHash != actualHash)
std::string(computedMD5, 32));
if (expectedMD5sum != actualMD5sum)
{ {
cmOStringStream oss; cmOStringStream oss;
oss << "DOWNLOAD MD5 mismatch" << std::endl oss << "DOWNLOAD HASH mismatch" << std::endl
<< " for file: [" << file << "]" << std::endl << " for file: [" << file << "]" << std::endl
<< " expected MD5 sum: [" << expectedMD5sum << "]" << std::endl << " expected hash: [" << expectedHash << "]" << std::endl
<< " actual MD5 sum: [" << actualMD5sum << "]" << std::endl << " actual hash: [" << actualHash << "]" << std::endl
; ;
this->SetError(oss.str().c_str()); this->SetError(oss.str().c_str());
return false; return false;

View File

@ -83,6 +83,7 @@ public:
" file(TO_NATIVE_PATH path result)\n" " file(TO_NATIVE_PATH path result)\n"
" file(DOWNLOAD url file [INACTIVITY_TIMEOUT timeout]\n" " file(DOWNLOAD url file [INACTIVITY_TIMEOUT timeout]\n"
" [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS]\n" " [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS]\n"
" [EXPECTED_HASH MD5|SHA1|SHA224|SHA256|SHA384|SHA512 hash]\n"
" [EXPECTED_MD5 sum])\n" " [EXPECTED_MD5 sum])\n"
" file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout]\n" " file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout]\n"
" [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS])\n" " [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS])\n"
@ -168,11 +169,12 @@ public:
"timeout after time seconds, time should be specified as an integer. " "timeout after time seconds, time should be specified as an integer. "
"The INACTIVITY_TIMEOUT specifies an integer number of seconds of " "The INACTIVITY_TIMEOUT specifies an integer number of seconds of "
"inactivity after which the operation should terminate. " "inactivity after which the operation should terminate. "
"If EXPECTED_MD5 sum is specified, the operation will verify that the " "If EXPECTED_HASH is specified, the operation will verify that the "
"downloaded file's actual md5 sum matches the expected value. If it " "downloaded file's actual hash matches the expected value. If it "
"does not match, the operation fails with an error. " "does not match, the operation fails with an error. "
"(EXPECTED_MD5 is short-hand for EXPECTED_HASH MD5.) "
"If SHOW_PROGRESS is specified, progress information will be printed " "If SHOW_PROGRESS is specified, progress information will be printed "
"as status messages until the operation is complete." "as status messages until the operation is complete. "
"\n" "\n"
"UPLOAD will upload the given file to the given URL. " "UPLOAD will upload the given file to the given URL. "
"If LOG var is specified a log of the upload will be put in var. " "If LOG var is specified a log of the upload will be put in var. "

View File

@ -33,6 +33,59 @@ file(DOWNLOAD
) )
message(STATUS "FileDownload:4") message(STATUS "FileDownload:4")
file(DOWNLOAD
${url}
${dir}/file3.png
TIMEOUT 2
STATUS status
EXPECTED_HASH SHA1 50c614fc28b39c1281d0517bb6d5858b4359c9b7
)
message(STATUS "FileDownload:5")
file(DOWNLOAD
${url}
${dir}/file3.png
TIMEOUT 2
STATUS status
EXPECTED_HASH SHA224 73cd5f442b04e8320e4f907f8e1b21d4befff98b5bd77bc32526ea68
)
message(STATUS "FileDownload:6")
file(DOWNLOAD
${url}
${dir}/file3.png
TIMEOUT 2
STATUS status
EXPECTED_HASH SHA256 2e067f6c09cbc7cd619c8fbcc44eb64cd6b45a95e4cddb3a585eee1f731c4da9
)
message(STATUS "FileDownload:7")
file(DOWNLOAD
${url}
${dir}/file3.png
TIMEOUT 2
STATUS status
EXPECTED_HASH SHA384 398bf41902a7251c30e522b307e3e41e3fb617c765b3feaa99b2f7d063894708ad399267ccc25d877437a10e5e890d35
)
message(STATUS "FileDownload:8")
file(DOWNLOAD
${url}
${dir}/file3.png
TIMEOUT 2
STATUS status
EXPECTED_HASH SHA512 c51854d21052713968b849c2b4263cf54be03bc3a7e9847a6c71c6c8d1d13cd805fe1b9fa95f9ba1d0a5631513974f6fae21e34ab5b171d94bad48df5f073e48
)
message(STATUS "FileDownload:9")
file(DOWNLOAD
${url}
${dir}/file3.png
TIMEOUT 2
STATUS status
EXPECTED_HASH MD5 d16778650db435bda3a8c3435c3ff5d1
)
message(STATUS "FileDownload:10")
file(DOWNLOAD file(DOWNLOAD
${url} ${url}
${dir}/file3.png ${dir}/file3.png