mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-12 10:04:14 +02:00
Add base64 encode/decode.
This commit is contained in:
parent
2d56de00fc
commit
f4524aeaa9
@ -63,6 +63,10 @@
|
||||
<release-item>
|
||||
<p>Add C memory contexts.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<p>Add base64 encode/decode.</p>
|
||||
</release-item>
|
||||
</release-refactor-list>
|
||||
</release-core-list>
|
||||
|
||||
|
@ -25,6 +25,7 @@ C includes
|
||||
|
||||
These includes are from the src directory. There is no Perl-specific code in them.
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/encode.h"
|
||||
#include "common/error.h"
|
||||
#include "config/config.h"
|
||||
#include "config/configRule.h"
|
||||
@ -35,6 +36,13 @@ Helper macros
|
||||
***********************************************************************************************************************************/
|
||||
#include "LibC.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
XSH includes
|
||||
|
||||
These includes define data structures that are required for the C to Perl interface but are not part of the regular C source.
|
||||
***********************************************************************************************************************************/
|
||||
#include "xs/common/encode.xsh"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Constant include
|
||||
|
||||
@ -58,6 +66,7 @@ INCLUDE: const-xs.inc
|
||||
#
|
||||
# These modules should map 1-1 with C modules in src directory.
|
||||
# ----------------------------------------------------------------------------------------------------------------------------------
|
||||
INCLUDE: xs/common/encode.xs
|
||||
INCLUDE: xs/config/config.xs
|
||||
INCLUDE: xs/config/configRule.xs
|
||||
INCLUDE: xs/postgres/pageChecksum.xs
|
||||
|
@ -101,6 +101,17 @@ my $rhExport =
|
||||
libCVersion
|
||||
)],
|
||||
},
|
||||
|
||||
'encode' =>
|
||||
{
|
||||
&BLD_EXPORTTYPE_CONSTANT => [qw(
|
||||
ENCODE_TYPE_BASE64
|
||||
)],
|
||||
|
||||
&BLD_EXPORTTYPE_SUB => [qw(
|
||||
encodeToStr decodeToBin
|
||||
)],
|
||||
},
|
||||
};
|
||||
|
||||
####################################################################################################################################
|
||||
|
48
libc/xs/common/encode.xs
Normal file
48
libc/xs/common/encode.xs
Normal file
@ -0,0 +1,48 @@
|
||||
# ----------------------------------------------------------------------------------------------------------------------------------
|
||||
# Binary to String Encode/Decode Perl Exports
|
||||
# ----------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
MODULE = pgBackRest::LibC PACKAGE = pgBackRest::LibC
|
||||
|
||||
####################################################################################################################################
|
||||
SV *
|
||||
encodeToStr(encodeType, source)
|
||||
int encodeType
|
||||
SV *source
|
||||
CODE:
|
||||
RETVAL = NULL;
|
||||
|
||||
STRLEN sourceSize;
|
||||
unsigned char *sourcePtr = (unsigned char *)SvPV(source, sourceSize);
|
||||
|
||||
ERROR_XS_BEGIN()
|
||||
{
|
||||
RETVAL = newSV(encodeToStrSize(encodeType, sourceSize));
|
||||
SvPOK_only(RETVAL);
|
||||
|
||||
encodeToStr(encodeType, sourcePtr, sourceSize, (char *)SvPV_nolen(RETVAL));
|
||||
SvCUR_set(RETVAL, encodeToStrSize(encodeType, sourceSize));
|
||||
}
|
||||
ERROR_XS_END();
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
####################################################################################################################################
|
||||
SV *
|
||||
decodeToBin(encodeType, source)
|
||||
int encodeType
|
||||
const char *source
|
||||
CODE:
|
||||
RETVAL = NULL;
|
||||
|
||||
ERROR_XS_BEGIN()
|
||||
{
|
||||
RETVAL = newSV(decodeToBinSize(encodeType, source));
|
||||
SvPOK_only(RETVAL);
|
||||
|
||||
decodeToBin(encodeType, source, (unsigned char *)SvPV_nolen(RETVAL));
|
||||
SvCUR_set(RETVAL, decodeToBinSize(encodeType, source));
|
||||
}
|
||||
ERROR_XS_END();
|
||||
OUTPUT:
|
||||
RETVAL
|
7
libc/xs/common/encode.xsh
Normal file
7
libc/xs/common/encode.xsh
Normal file
@ -0,0 +1,7 @@
|
||||
/***********************************************************************************************************************************
|
||||
Binary to String Encode/Decode XS Header
|
||||
***********************************************************************************************************************************/
|
||||
#include "../src/common/encode.h"
|
||||
|
||||
// Encode types
|
||||
#define ENCODE_TYPE_BASE64 ((int)encodeBase64)
|
102
src/common/encode.c
Normal file
102
src/common/encode.c
Normal file
@ -0,0 +1,102 @@
|
||||
/***********************************************************************************************************************************
|
||||
Binary to String Encode/Decode
|
||||
***********************************************************************************************************************************/
|
||||
#include <string.h>
|
||||
|
||||
#include "common/encode.h"
|
||||
#include "common/encode/base64.h"
|
||||
#include "common/error.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macro to handle invalid encode type errors
|
||||
***********************************************************************************************************************************/
|
||||
#define ENCODE_TYPE_INVALID_ERROR(encodeType) \
|
||||
ERROR_THROW(AssertError, "invalid encode type %d", encodeType);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Encode binary data to a printable string
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
encodeToStr(EncodeType encodeType, const unsigned char *source, int sourceSize, char *destination)
|
||||
{
|
||||
if (encodeType == encodeBase64)
|
||||
encodeToStrBase64(source, sourceSize, destination);
|
||||
else
|
||||
ENCODE_TYPE_INVALID_ERROR(encodeType);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Size of the string returned by encodeToStr()
|
||||
***********************************************************************************************************************************/
|
||||
int
|
||||
encodeToStrSize(EncodeType encodeType, int sourceSize)
|
||||
{
|
||||
int destinationSize = 0;
|
||||
|
||||
if (encodeType == encodeBase64)
|
||||
destinationSize = encodeToStrSizeBase64(sourceSize);
|
||||
else
|
||||
ENCODE_TYPE_INVALID_ERROR(encodeType);
|
||||
|
||||
return destinationSize;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Decode a string to binary data
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
decodeToBin(EncodeType encodeType, const char *source, unsigned char *destination)
|
||||
{
|
||||
if (encodeType == encodeBase64)
|
||||
decodeToBinBase64(source, destination);
|
||||
else
|
||||
ENCODE_TYPE_INVALID_ERROR(encodeType);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Size of the binary data returned by decodeToBin()
|
||||
***********************************************************************************************************************************/
|
||||
int
|
||||
decodeToBinSize(EncodeType encodeType, const char *source)
|
||||
{
|
||||
int destinationSize = 0;
|
||||
|
||||
if (encodeType == encodeBase64)
|
||||
destinationSize = decodeToBinSizeBase64(source);
|
||||
else
|
||||
ENCODE_TYPE_INVALID_ERROR(encodeType);
|
||||
|
||||
return destinationSize;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Check that the encoded string is valid
|
||||
***********************************************************************************************************************************/
|
||||
bool
|
||||
decodeToBinValid(EncodeType encodeType, const char *source)
|
||||
{
|
||||
bool valid = true;
|
||||
|
||||
ERROR_TRY()
|
||||
{
|
||||
decodeToBinValidate(encodeType, source);
|
||||
}
|
||||
ERROR_CATCH(FormatError)
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Validate the encoded string
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
decodeToBinValidate(EncodeType encodeType, const char *source)
|
||||
{
|
||||
if (encodeType == encodeBase64)
|
||||
decodeToBinValidateBase64(source);
|
||||
else
|
||||
ENCODE_TYPE_INVALID_ERROR(encodeType);
|
||||
}
|
26
src/common/encode.h
Normal file
26
src/common/encode.h
Normal file
@ -0,0 +1,26 @@
|
||||
/***********************************************************************************************************************************
|
||||
Binary to String Encode/Decode
|
||||
|
||||
These high-level functions are preferred to the low-level functions for each encoding type in the encode subdirectory.
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef ENCODE_H
|
||||
#define ENCODE_H
|
||||
|
||||
#include "common/type.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Encoding types
|
||||
***********************************************************************************************************************************/
|
||||
typedef enum {encodeBase64} EncodeType;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
void encodeToStr(EncodeType encodeType, const unsigned char *source, int sourceSize, char *destination);
|
||||
int encodeToStrSize(EncodeType encodeType, int sourceSize);
|
||||
void decodeToBin(EncodeType encodeType, const char *source, unsigned char *destination);
|
||||
int decodeToBinSize(EncodeType encodeType, const char *source);
|
||||
bool decodeToBinValid(EncodeType encodeType, const char *source);
|
||||
void decodeToBinValidate(EncodeType encodeType, const char *source);
|
||||
|
||||
#endif
|
176
src/common/encode/base64.c
Normal file
176
src/common/encode/base64.c
Normal file
@ -0,0 +1,176 @@
|
||||
/***********************************************************************************************************************************
|
||||
Base64 Binary to String Encode/Decode
|
||||
***********************************************************************************************************************************/
|
||||
#include <string.h>
|
||||
|
||||
#include "common/encode/base64.h"
|
||||
#include "common/error.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Encode binary data to a printable string
|
||||
***********************************************************************************************************************************/
|
||||
static const char encodeBase64Lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
void
|
||||
encodeToStrBase64(const unsigned char *source, int sourceSize, char *destination)
|
||||
{
|
||||
int destinationIdx = 0;
|
||||
|
||||
// Encode the string from three bytes to four characters
|
||||
for (int sourceIdx = 0; sourceIdx < sourceSize; sourceIdx += 3)
|
||||
{
|
||||
// First two characters are always used
|
||||
destination[destinationIdx++] = encodeBase64Lookup[source[sourceIdx] >> 2];
|
||||
destination[destinationIdx++] =
|
||||
encodeBase64Lookup[((source[sourceIdx] & 0x03) << 4) | ((source[sourceIdx + 1] & 0xf0) >> 4)];
|
||||
|
||||
// Last two may be coded as = if there are less than three characters
|
||||
if (sourceSize - sourceIdx > 1)
|
||||
{
|
||||
destination[destinationIdx++] =
|
||||
encodeBase64Lookup[((source[sourceIdx + 1] & 0x0f) << 2) | ((source[sourceIdx + 2] & 0xc0) >> 6)];
|
||||
}
|
||||
else
|
||||
destination[destinationIdx++] = 0x3d;
|
||||
|
||||
if (sourceSize - sourceIdx > 2)
|
||||
destination[destinationIdx++] = encodeBase64Lookup[source[sourceIdx + 2] & 0x3f];
|
||||
else
|
||||
destination[destinationIdx++] = 0x3d;
|
||||
}
|
||||
|
||||
// Zero-terminate the string
|
||||
destination[destinationIdx] = 0;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Size of the destination param required by encodeToStrBase64() minus space for the null terminator
|
||||
***********************************************************************************************************************************/
|
||||
int
|
||||
encodeToStrSizeBase64(int sourceSize)
|
||||
{
|
||||
// Calculate how many groups of three are in the source
|
||||
int encodeGroupTotal = sourceSize / 3;
|
||||
|
||||
// Increase by one if there is a partial group
|
||||
if (sourceSize % 3 != 0)
|
||||
encodeGroupTotal++;
|
||||
|
||||
// Four characters are needed to encode each group
|
||||
return encodeGroupTotal * 4;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Decode a string to binary data
|
||||
***********************************************************************************************************************************/
|
||||
static const int decodeBase64Lookup[256] =
|
||||
{
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
|
||||
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
};
|
||||
|
||||
void
|
||||
decodeToBinBase64(const char *source, unsigned char *destination)
|
||||
{
|
||||
// Validate encoded string
|
||||
decodeToBinValidateBase64(source);
|
||||
|
||||
int destinationIdx = 0;
|
||||
|
||||
// Decode the binary data from four characters to three bytes
|
||||
for (int sourceIdx = 0; sourceIdx < strlen(source); sourceIdx += 4)
|
||||
{
|
||||
// Always decode the first character
|
||||
destination[destinationIdx++] =
|
||||
(unsigned char)(decodeBase64Lookup[(int)source[sourceIdx]] << 2 | decodeBase64Lookup[(int)source[sourceIdx + 1]] >> 4);
|
||||
|
||||
// Second character is optional
|
||||
if (source[sourceIdx + 2] != 0x3d)
|
||||
{
|
||||
destination[destinationIdx++] = (unsigned char)
|
||||
(decodeBase64Lookup[(int)source[sourceIdx + 1]] << 4 | decodeBase64Lookup[(int)source[sourceIdx + 2]] >> 2);
|
||||
}
|
||||
|
||||
// Third character is optional
|
||||
if (source[sourceIdx + 3] != 0x3d)
|
||||
{
|
||||
destination[destinationIdx++] = (unsigned char)
|
||||
(((decodeBase64Lookup[(int)source[sourceIdx + 2]] << 6) & 0xc0) | decodeBase64Lookup[(int)source[sourceIdx + 3]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Size of the destination param required by decodeToBinBase64()
|
||||
***********************************************************************************************************************************/
|
||||
int
|
||||
decodeToBinSizeBase64(const char *source)
|
||||
{
|
||||
// Validate encoded string
|
||||
decodeToBinValidateBase64(source);
|
||||
|
||||
// Start with size calculated directly from source length
|
||||
int sourceSize = strlen(source);
|
||||
int destinationSize = sourceSize / 4 * 3;
|
||||
|
||||
// Subtract last character if it is not present
|
||||
if (source[sourceSize - 1] == 0x3d)
|
||||
{
|
||||
destinationSize--;
|
||||
|
||||
// Subtract second to last character if it is not present
|
||||
if (source[sourceSize - 2] == 0x3d)
|
||||
destinationSize--;
|
||||
}
|
||||
|
||||
return destinationSize;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Validate the encoded string
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
decodeToBinValidateBase64(const char *source)
|
||||
{
|
||||
// Check for the correct length
|
||||
int sourceSize = strlen(source);
|
||||
|
||||
if (sourceSize % 4 != 0)
|
||||
ERROR_THROW(FormatError, "base64 size %d is not evenly divisible by 4", sourceSize);
|
||||
|
||||
// Check all characters
|
||||
for (int sourceIdx = 0; sourceIdx < sourceSize; sourceIdx++)
|
||||
{
|
||||
// Check terminators
|
||||
if (source[sourceIdx] == 0x3d)
|
||||
{
|
||||
// Make sure they are only in the last two positions
|
||||
if (sourceIdx < sourceSize - 2)
|
||||
ERROR_THROW(FormatError, "base64 '=' character may only appear in last two positions");
|
||||
|
||||
// If second to last char is = then last char must also be
|
||||
if (sourceIdx == sourceSize - 2 && source[sourceSize - 1] != 0x3d)
|
||||
ERROR_THROW(FormatError, "base64 last character must be '=' if second to last is");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error on any invalid characters
|
||||
if (decodeBase64Lookup[(int)source[sourceIdx]] == -1)
|
||||
ERROR_THROW(FormatError, "base64 invalid character found at position %d", sourceIdx);
|
||||
}
|
||||
}
|
||||
}
|
20
src/common/encode/base64.h
Normal file
20
src/common/encode/base64.h
Normal file
@ -0,0 +1,20 @@
|
||||
/***********************************************************************************************************************************
|
||||
Base64 Binary to String Encode/Decode
|
||||
|
||||
The high-level functions in encode.c should be used in preference to these low-level functions.
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef BASE64_H
|
||||
#define BASE64_H
|
||||
|
||||
#include "common/type.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
void encodeToStrBase64(const unsigned char *source, int sourceSize, char *destination);
|
||||
int encodeToStrSizeBase64(int sourceSize);
|
||||
void decodeToBinBase64(const char *source, unsigned char *destination);
|
||||
int decodeToBinSizeBase64(const char *source);
|
||||
void decodeToBinValidateBase64(const char *source);
|
||||
|
||||
#endif
|
@ -30,6 +30,7 @@ Define errors
|
||||
***********************************************************************************************************************************/
|
||||
ERROR_DEFINE(ERROR_CODE_MIN, AssertError, RuntimeError);
|
||||
|
||||
ERROR_DEFINE(ERROR_CODE_MIN + 04, FormatError, RuntimeError);
|
||||
ERROR_DEFINE(ERROR_CODE_MIN + 69, MemoryError, RuntimeError);
|
||||
|
||||
ERROR_DEFINE(ERROR_CODE_MAX, RuntimeError, RuntimeError);
|
||||
|
@ -16,6 +16,7 @@ typedef struct ErrorType ErrorType;
|
||||
// Error types
|
||||
ERROR_DECLARE(AssertError);
|
||||
|
||||
ERROR_DECLARE(FormatError);
|
||||
ERROR_DECLARE(MemoryError);
|
||||
|
||||
ERROR_DECLARE(RuntimeError);
|
||||
|
@ -128,6 +128,22 @@ my $oTestDef =
|
||||
'common/memContext' => TESTDEF_COVERAGE_FULL,
|
||||
},
|
||||
},
|
||||
{
|
||||
&TESTDEF_NAME => 'encode',
|
||||
&TESTDEF_TOTAL => 1,
|
||||
&TESTDEF_C => true,
|
||||
|
||||
&TESTDEF_COVERAGE =>
|
||||
{
|
||||
'common/encode' => TESTDEF_COVERAGE_FULL,
|
||||
'common/encode/base64' => TESTDEF_COVERAGE_FULL,
|
||||
},
|
||||
},
|
||||
{
|
||||
&TESTDEF_NAME => 'encode-perl',
|
||||
&TESTDEF_TOTAL => 1,
|
||||
&TESTDEF_CLIB => true,
|
||||
},
|
||||
{
|
||||
&TESTDEF_NAME => 'http-client',
|
||||
&TESTDEF_TOTAL => 2,
|
||||
|
@ -0,0 +1,62 @@
|
||||
####################################################################################################################################
|
||||
# Test Binary to String Encode/Decode
|
||||
####################################################################################################################################
|
||||
package pgBackRestTest::Module::Common::CommonEncodePerlTest;
|
||||
use parent 'pgBackRestTest::Common::RunTest';
|
||||
|
||||
####################################################################################################################################
|
||||
# Perl includes
|
||||
####################################################################################################################################
|
||||
use strict;
|
||||
use warnings FATAL => qw(all);
|
||||
use Carp qw(confess);
|
||||
use English '-no_match_vars';
|
||||
|
||||
use pgBackRest::Common::Exception;
|
||||
use pgBackRest::Common::Ini;
|
||||
use pgBackRest::Common::Log;
|
||||
use pgBackRest::LibC qw(:encode);
|
||||
use pgBackRest::Version;
|
||||
|
||||
use pgBackRestTest::Common::ExecuteTest;
|
||||
use pgBackRestTest::Common::RunTest;
|
||||
|
||||
####################################################################################################################################
|
||||
# run
|
||||
####################################################################################################################################
|
||||
sub run
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
################################################################################################################################
|
||||
if ($self->begin("encodeToStrBase64() and decodeToBinBase64()"))
|
||||
{
|
||||
my $strData = 'string_to_encode';
|
||||
my $strEncodedData = 'c3RyaW5nX3RvX2VuY29kZQ==';
|
||||
|
||||
$self->testResult(sub {encodeToStr(ENCODE_TYPE_BASE64, $strData)}, $strEncodedData, 'encode string');
|
||||
$self->testResult(sub {decodeToBin(ENCODE_TYPE_BASE64, $strEncodedData)}, $strData, 'decode string');
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
my $tData =
|
||||
pack('C', 1) . pack('C', 2) . pack('C', 3) . pack('C', 4) . pack('C', 5) . pack('C', 4) . pack('C', 3) . pack('C', 2);
|
||||
my $tEncodedData = 'AQIDBAUEAwI=';
|
||||
|
||||
$self->testResult(sub {encodeToStr(ENCODE_TYPE_BASE64, $tData)}, $tEncodedData, 'encode binary');
|
||||
$self->testResult(sub {decodeToBin(ENCODE_TYPE_BASE64, $tEncodedData)}, $tData, 'decode binary');
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$tData .= pack('C', 1);
|
||||
$tEncodedData = 'AQIDBAUEAwIB';
|
||||
|
||||
$self->testResult(sub {encodeToStr(ENCODE_TYPE_BASE64, $tData)}, $tEncodedData, 'encode binary');
|
||||
$self->testResult(sub {decodeToBin(ENCODE_TYPE_BASE64, $tEncodedData)}, $tData, 'decode binary');
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------
|
||||
$self->testException(sub {encodeToStr(-1, '')}, ERROR_ASSERT, 'invalid encode type -1');
|
||||
$self->testException(
|
||||
sub {decodeToBin(ENCODE_TYPE_BASE64, "XX")}, ERROR_FORMAT, 'base64 size 2 is not evenly divisible by 4');
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
105
test/src/module/common/encodeTest.c
Normal file
105
test/src/module/common/encodeTest.c
Normal file
@ -0,0 +1,105 @@
|
||||
/***********************************************************************************************************************************
|
||||
Test Binary to String Encode/Decode
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test Run
|
||||
***********************************************************************************************************************************/
|
||||
void testRun()
|
||||
{
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
if (testBegin("base64"))
|
||||
{
|
||||
char *source = "string_to_encode\r\n";
|
||||
unsigned char destination[256];
|
||||
|
||||
encodeToStr(encodeBase64, source, 1, destination);
|
||||
TEST_RESULT_STR(destination, "c3==", "1 character encode");
|
||||
TEST_RESULT_INT(encodeToStrSize(encodeBase64, 1), strlen(destination), "check size");
|
||||
|
||||
encodeToStr(encodeBase64, source, 2, destination);
|
||||
TEST_RESULT_STR(destination, "c3R=", "2 character encode");
|
||||
TEST_RESULT_INT(encodeToStrSize(encodeBase64, 2), strlen(destination), "check size");
|
||||
|
||||
encodeToStr(encodeBase64, source, 3, destination);
|
||||
TEST_RESULT_STR(destination, "c3Ry", "3 character encode");
|
||||
TEST_RESULT_INT(encodeToStrSize(encodeBase64, 3), strlen(destination), "check size");
|
||||
|
||||
encodeToStr(encodeBase64, source, strlen(source) - 2, destination);
|
||||
TEST_RESULT_STR(destination, "c3RyaW5nX3RvX2VuY29kZQ==", "encode full string");
|
||||
TEST_RESULT_INT(encodeToStrSize(encodeBase64, strlen(source) - 2), strlen(destination), "check size");
|
||||
|
||||
encodeToStr(encodeBase64, source, strlen(source), destination);
|
||||
TEST_RESULT_STR(destination, "c3RyaW5nX3RvX2VuY29kZQ0K", "encode full string with \\r\\n");
|
||||
TEST_RESULT_INT(encodeToStrSize(encodeBase64, strlen(source)), strlen(destination), "check size");
|
||||
|
||||
encodeToStr(encodeBase64, source, strlen(source) + 1, destination);
|
||||
TEST_RESULT_STR(destination, "c3RyaW5nX3RvX2VuY29kZQ0KAG==", "encode full string with \\r\\n and null");
|
||||
TEST_RESULT_INT(encodeToStrSize(encodeBase64, strlen(source) + 1), strlen(destination), "check size");
|
||||
|
||||
TEST_ERROR(encodeToStr(999, source, strlen(source), destination), AssertError, "invalid encode type 999");
|
||||
TEST_ERROR(encodeToStrSize(999, strlen(source)), AssertError, "invalid encode type 999");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
memset(destination, 0xFF, sizeof(destination));
|
||||
char *decode = "c3RyaW5nX3RvX2VuY29kZQ0KAG==";
|
||||
decodeToBin(encodeBase64, decode, destination);
|
||||
TEST_RESULT_STR(destination, source, "full string with \\r\\n and null decode");
|
||||
TEST_RESULT_INT(destination[strlen(source) + 1], 0xFF, "check for overrun");
|
||||
TEST_RESULT_INT(decodeToBinSize(encodeBase64, decode), strlen(source) + 1, "check size");
|
||||
|
||||
memset(destination, 0xFF, sizeof(destination));
|
||||
decode = "c3RyaW5nX3RvX2VuY29kZQ0K";
|
||||
decodeToBin(encodeBase64, decode, destination);
|
||||
TEST_RESULT_INT(memcmp(destination, source, strlen(source)), 0, "full string with \\r\\n decode");
|
||||
TEST_RESULT_INT(destination[strlen(source)], 0xFF, "check for overrun");
|
||||
TEST_RESULT_INT(decodeToBinSize(encodeBase64, decode), strlen(source), "check size");
|
||||
|
||||
memset(destination, 0xFF, sizeof(destination));
|
||||
decode = "c3RyaW5nX3RvX2VuY29kZQ==";
|
||||
decodeToBin(encodeBase64, decode, destination);
|
||||
TEST_RESULT_INT(memcmp(destination, source, strlen(source) - 2), 0, "full string decode");
|
||||
TEST_RESULT_INT(destination[strlen(source) - 2], 0xFF, "check for overrun");
|
||||
TEST_RESULT_INT(decodeToBinSize(encodeBase64, decode), strlen(source) - 2, "check size");
|
||||
|
||||
memset(destination, 0xFF, sizeof(destination));
|
||||
decode = "c3Ry";
|
||||
decodeToBin(encodeBase64, decode, destination);
|
||||
TEST_RESULT_INT(memcmp(destination, source, 3), 0, "3 character decode");
|
||||
TEST_RESULT_INT(destination[3], 0xFF, "check for overrun");
|
||||
TEST_RESULT_INT(decodeToBinSize(encodeBase64, decode), 3, "check size");
|
||||
|
||||
memset(destination, 0xFF, sizeof(destination));
|
||||
decode = "c3R=";
|
||||
decodeToBin(encodeBase64, decode, destination);
|
||||
TEST_RESULT_INT(memcmp(destination, source, 2), 0, "2 character decode");
|
||||
TEST_RESULT_INT(destination[2], 0xFF, "check for overrun");
|
||||
TEST_RESULT_INT(decodeToBinSize(encodeBase64, decode), 2, "check size");
|
||||
|
||||
memset(destination, 0xFF, sizeof(destination));
|
||||
decode = "c3==";
|
||||
decodeToBin(encodeBase64, decode, destination);
|
||||
TEST_RESULT_INT(memcmp(destination, source, 1), 0, "1 character decode");
|
||||
TEST_RESULT_INT(destination[1], 0xFF, "check for overrun");
|
||||
TEST_RESULT_INT(decodeToBinSize(encodeBase64, decode), 1, "check size");
|
||||
|
||||
TEST_ERROR(decodeToBin(-1, decode, destination), AssertError, "invalid encode type -1");
|
||||
TEST_ERROR(decodeToBinSize(-1, decode), AssertError, "invalid encode type -1");
|
||||
TEST_ERROR(decodeToBin(encodeBase64, "cc$=", destination), FormatError, "base64 invalid character found at position 2");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ERROR(decodeToBinValidate(encodeBase64, "c3"), FormatError, "base64 size 2 is not evenly divisible by 4");
|
||||
TEST_ERROR(
|
||||
decodeToBinValidate(encodeBase64, "c==="), FormatError, "base64 '=' character may only appear in last two positions");
|
||||
TEST_ERROR(
|
||||
decodeToBinValidate(encodeBase64, "cc=c"), FormatError, "base64 last character must be '=' if second to last is");
|
||||
|
||||
TEST_ERROR(decodeToBinValidate(9999, "cc=c"), AssertError, "invalid encode type 9999");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_RESULT_BOOL(decodeToBinValid(encodeBase64, "CCCCCCCCCCC"), false, "base64 string not valid");
|
||||
TEST_RESULT_BOOL(decodeToBinValid(encodeBase64, "CCCCCCCCCCCC"), true, "base64 string valid");
|
||||
|
||||
TEST_ERROR(decodeToBinValid(-999, "CCCCCCCCCCCC"), AssertError, "invalid encode type -999");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user