Merge topic 'autogen-base32'

228f4e9b cmFilePathUuid: Use Base32 string instead of Base64 string
b481ddb3 Add cmBase32Encoder class
This commit is contained in:
Brad King 2016-09-02 09:22:31 -04:00 committed by CMake Topic Stage
commit e47bb01837
4 changed files with 158 additions and 13 deletions

View File

@ -166,6 +166,7 @@ endif()
#
set(SRCS
cmArchiveWrite.cxx
cmBase32.cxx
cmBootstrapCommands1.cxx
cmBootstrapCommands2.cxx
cmCacheManager.cxx

108
Source/cmBase32.cxx Normal file
View File

@ -0,0 +1,108 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2016 Sebastian Holtermann <sebholt@xwmw.org>
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "cmBase32.h"
// -- Static functions
static const unsigned char Base32EncodeTable[33] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
inline unsigned char Base32EncodeChar(int schar)
{
return Base32EncodeTable[schar];
}
void Base32Encode5(const unsigned char src[5], char dst[8])
{
// [0]:5 bits
dst[0] = Base32EncodeChar((src[0] >> 3) & 0x1F);
// [0]:3 bits + [1]:2 bits
dst[1] = Base32EncodeChar(((src[0] << 2) & 0x1C) + ((src[1] >> 6) & 0x03));
// [1]:5 bits
dst[2] = Base32EncodeChar((src[1] >> 1) & 0x1F);
// [1]:1 bit + [2]:4 bits
dst[3] = Base32EncodeChar(((src[1] << 4) & 0x10) + ((src[2] >> 4) & 0x0F));
// [2]:4 bits + [3]:1 bit
dst[4] = Base32EncodeChar(((src[2] << 1) & 0x1E) + ((src[3] >> 7) & 0x01));
// [3]:5 bits
dst[5] = Base32EncodeChar((src[3] >> 2) & 0x1F);
// [3]:2 bits + [4]:3 bit
dst[6] = Base32EncodeChar(((src[3] << 3) & 0x18) + ((src[4] >> 5) & 0x07));
// [4]:5 bits
dst[7] = Base32EncodeChar((src[4] << 0) & 0x1F);
}
// -- Class methods
cmBase32Encoder::cmBase32Encoder()
{
}
cmBase32Encoder::~cmBase32Encoder()
{
}
std::string cmBase32Encoder::encodeString(const unsigned char* input,
size_t len, bool padding)
{
std::string res;
static const size_t blockSize = 5;
static const size_t bufferSize = 8;
char buffer[bufferSize];
const unsigned char* end = input + len;
while ((input + blockSize) <= end) {
Base32Encode5(input, buffer);
res.append(buffer, bufferSize);
input += blockSize;
}
size_t remain(end - input);
if (remain != 0) {
// Temporary source buffer filled up with 0s
unsigned char extended[blockSize];
for (size_t ii = 0; ii != remain; ++ii) {
extended[ii] = input[ii];
}
for (size_t ii = remain; ii != blockSize; ++ii) {
extended[ii] = 0;
}
Base32Encode5(extended, buffer);
size_t numPad(0);
switch (remain) {
case 1:
numPad = 6;
break;
case 2:
numPad = 4;
break;
case 3:
numPad = 3;
break;
case 4:
numPad = 1;
break;
default:
break;
}
res.append(buffer, bufferSize - numPad);
if (padding) {
for (size_t ii = 0; ii != numPad; ++ii) {
res.push_back(paddingChar);
}
}
}
return res;
}

42
Source/cmBase32.h Normal file
View File

@ -0,0 +1,42 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2016 Sebastian Holtermann <sebholt@xwmw.org>
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef cmBase32_h
#define cmBase32_h
#include <cmConfigure.h> // IWYU pragma: keep
#include <stddef.h>
#include <string>
/** \class cmBase32Encoder
* \brief Encodes a byte sequence to a Base32 byte sequence according to
* RFC4648
*
*/
class cmBase32Encoder
{
public:
static const char paddingChar = '=';
public:
cmBase32Encoder();
~cmBase32Encoder();
// Encodes the given input byte sequence into a string
// @arg input Input data pointer
// @arg len Input data size
// @arg padding Flag to append "=" on demand
std::string encodeString(const unsigned char* input, size_t len,
bool padding = true);
};
#endif

View File

@ -12,10 +12,10 @@
#include "cmFilePathUuid.h"
#include "cmBase32.h"
#include "cmCryptoHash.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmsys/Base64.h"
cmFilePathUuid::cmFilePathUuid(cmMakefile* makefile)
{
@ -111,22 +111,16 @@ std::string cmFilePathUuid::GetChecksumString(
const std::string& sourceFilename, const std::string& sourceRelPath,
const std::string& sourceRelSeed)
{
std::string checksumBase64;
std::string checksumBase32;
{
// Calculate the file ( seed + relative path + name ) checksum
std::vector<unsigned char> hashBytes =
cmCryptoHash::New("SHA256")->ByteHashString(
(sourceRelSeed + sourceRelPath + sourceFilename).c_str());
// Convert hash bytes to Base64 text string
std::vector<unsigned char> base64Bytes(hashBytes.size() * 2, 0);
cmsysBase64_Encode(&hashBytes[0], hashBytes.size(), &base64Bytes[0], 0);
checksumBase64 = reinterpret_cast<const char*>(&base64Bytes[0]);
}
// Base64 allows '/', '+' and '=' characters which are problematic
// when used in file names. Replace them with safer alternatives.
std::replace(checksumBase64.begin(), checksumBase64.end(), '/', '-');
std::replace(checksumBase64.begin(), checksumBase64.end(), '+', '_');
std::replace(checksumBase64.begin(), checksumBase64.end(), '=', '_');
return checksumBase64;
checksumBase32 =
cmBase32Encoder().encodeString(&hashBytes[0], hashBytes.size(), false);
}
return checksumBase32;
}