support base64 encode

pull/2104/head
莫战 4 years ago committed by winlin
parent 58b75c6f1b
commit dc7124cd05

@ -926,17 +926,18 @@ uint32_t srs_crc32_mpegts(const void* buf, int size)
return __crc32_table_driven(__crc32_MPEG_table, buf, size, 0x00, reflect_in, xor_in, reflect_out, xor_out);
}
// We use the standard encoding:
// var StdEncoding = NewEncoding(encodeStd)
// StdEncoding is the standard base64 encoding, as defined in RFC 4648.
namespace {
char padding = '=';
string encoder = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
}
// @see golang encoding/base64/base64.go
srs_error_t srs_av_base64_decode(string cipher, string& plaintext)
{
srs_error_t err = srs_success;
// We use the standard encoding:
// var StdEncoding = NewEncoding(encodeStd)
// StdEncoding is the standard base64 encoding, as defined in RFC 4648.
char padding = '=';
string encoder = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
uint8_t decodeMap[256];
memset(decodeMap, 0xff, sizeof(decodeMap));
@ -1036,6 +1037,67 @@ srs_error_t srs_av_base64_decode(string cipher, string& plaintext)
return err;
}
// @see golang encoding/base64/base64.go
srs_error_t srs_av_base64_encode(std::string plaintext, std::string& cipher)
{
srs_error_t err = srs_success;
uint8_t decodeMap[256];
memset(decodeMap, 0xff, sizeof(decodeMap));
for (int i = 0; i < (int)encoder.length(); i++) {
decodeMap[(uint8_t)encoder.at(i)] = uint8_t(i);
}
cipher.clear();
uint32_t val = 0;
int di = 0;
int si = 0;
int n = (plaintext.length() / 3) * 3;
uint8_t* p = (uint8_t*)plaintext.c_str();
while(si < n) {
// Convert 3x 8bit source bytes into 4 bytes
uint32_t v1 = uint32_t(p[si+0]) << 16;
uint32_t v2 = uint32_t(p[si+1]) << 8;
uint32_t v3 = uint32_t(p[si+2]);
val = (uint32_t(p[si + 0]) << 16) | (uint32_t(p[si + 1])<< 8) | uint32_t(p[si + 2]);
cipher += encoder[val>>18&0x3f];
cipher += encoder[val>>12&0x3f];
cipher += encoder[val>>6&0x3f];
cipher += encoder[val&0x3f];
si += 3;
di += 4;
}
int remain = plaintext.length() - si;
if(0 == remain) {
return err;
}
val = uint32_t(p[si + 0]) << 16;
if( 2 == remain) {
val |= uint32_t(p[si + 1]) << 8;
}
cipher += encoder[val>>18&0x3f];
cipher += encoder[val>>12&0x3f];
switch (remain) {
case 2:
cipher += encoder[val>>6&0x3f];
cipher += padding;
break;
case 1:
cipher += padding;
cipher += padding;
break;
}
return err;
}
#define SPACE_CHARS " \t\r\n"
int av_toupper(int c)

@ -141,6 +141,8 @@ extern uint32_t srs_crc32_ieee(const void* buf, int size, uint32_t previous = 0)
// Decode a base64-encoded string.
extern srs_error_t srs_av_base64_decode(std::string cipher, std::string& plaintext);
// Encode a plaintext to base64-encoded string.
extern srs_error_t srs_av_base64_encode(std::string plaintext, std::string& cipher);
// Calculate the output size needed to base64-encode x bytes to a null-terminated string.
#define SRS_AV_BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1)

@ -2393,6 +2393,89 @@ VOID TEST(KernelUtility, Base64Decode)
EXPECT_TRUE(expect == plaintext);
}
VOID TEST(KernelUtility, Base64Encode)
{
srs_error_t err;
string expect = "dXNlcjpwYXNzd29yZA==";
string plaintext = "user:password";
string cipher;
HELPER_EXPECT_SUCCESS(srs_av_base64_encode(plaintext, cipher));
EXPECT_TRUE(expect == cipher);
}
VOID TEST(KernelUtility, Base64)
{
srs_error_t err = srs_success;
struct testpair {
string decoded;
string encoded;
};
struct testpair data[] = {
// RFC 3548 examples
{"\x14\xfb\x9c\x03\xd9\x7e", "FPucA9l+"},
{"\x14\xfb\x9c\x03\xd9", "FPucA9k="},
{"\x14\xfb\x9c\x03", "FPucAw=="},
// RFC 4648 examples
{"", ""},
{"f", "Zg=="},
{"fo", "Zm8="},
{"foo", "Zm9v"},
{"foob", "Zm9vYg=="},
{"fooba", "Zm9vYmE="},
{"foobar", "Zm9vYmFy"},
// Wikipedia examples
{"sure.", "c3VyZS4="},
{"sure", "c3VyZQ=="},
{"sur", "c3Vy"},
{"su", "c3U="},
{"leasure.", "bGVhc3VyZS4="},
{"easure.", "ZWFzdXJlLg=="},
{"asure.", "YXN1cmUu"},
{"sure.", "c3VyZS4="},
{"Twas brillig, and the slithy toves", "VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw=="}
};
for(int i = 0; i < (sizeof(data) / sizeof(struct testpair)); ++i) {
struct testpair& d = data[i];
string cipher;
HELPER_EXPECT_SUCCESS(srs_av_base64_encode(d.decoded, cipher));
EXPECT_STREQ(d.encoded.c_str(), cipher.c_str());
string plaintext;
HELPER_EXPECT_SUCCESS(srs_av_base64_decode(d.encoded, plaintext));
EXPECT_STREQ(d.decoded.c_str(), plaintext.c_str());
}
string expected = "sure";
string examples[11] = {
"c3VyZQ==",
"c3VyZQ==\r",
"c3VyZQ==\n",
"c3VyZQ==\r\n",
"c3VyZ\r\nQ==",
"c3V\ryZ\nQ==",
"c3V\nyZ\rQ==",
"c3VyZ\nQ==",
"c3VyZQ\n==",
"c3VyZQ=\n=",
"c3VyZQ=\r\n\r\n=",
};
for(int i = 0; i < 11; ++i) {
string& encoded_str = examples[i];
string plaintext;
HELPER_EXPECT_SUCCESS(srs_av_base64_decode(encoded_str, plaintext));
EXPECT_STREQ(expected.c_str(), plaintext.c_str());
}
}
VOID TEST(KernelUtility, StringToHex)
{
if (true) {

Loading…
Cancel
Save