Просмотр исходного кода

Merge topic 'autogen-base32'

228f4e9b cmFilePathUuid: Use Base32 string instead of Base64 string
b481ddb3 Add cmBase32Encoder class
Brad King 9 лет назад
Родитель
Сommit
e47bb01837
4 измененных файлов с 157 добавлено и 12 удалено
  1. 1 0
      Source/CMakeLists.txt
  2. 108 0
      Source/cmBase32.cxx
  3. 42 0
      Source/cmBase32.h
  4. 6 12
      Source/cmFilePathUuid.cxx

+ 1 - 0
Source/CMakeLists.txt

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

+ 108 - 0
Source/cmBase32.cxx

@@ -0,0 +1,108 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2016 Sebastian Holtermann <[email protected]>
+
+  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 - 0
Source/cmBase32.h

@@ -0,0 +1,42 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2016 Sebastian Holtermann <[email protected]>
+
+  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

+ 6 - 12
Source/cmFilePathUuid.cxx

@@ -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]);
+
+    checksumBase32 =
+      cmBase32Encoder().encodeString(&hashBytes[0], hashBytes.size(), false);
   }
-  // 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;
+  return checksumBase32;
 }