mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
support base64 encode
This commit is contained in:
parent
58b75c6f1b
commit
dc7124cd05
3 changed files with 153 additions and 6 deletions
|
@ -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);
|
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
|
// @see golang encoding/base64/base64.go
|
||||||
srs_error_t srs_av_base64_decode(string cipher, string& plaintext)
|
srs_error_t srs_av_base64_decode(string cipher, string& plaintext)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
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];
|
uint8_t decodeMap[256];
|
||||||
memset(decodeMap, 0xff, sizeof(decodeMap));
|
memset(decodeMap, 0xff, sizeof(decodeMap));
|
||||||
|
|
||||||
|
@ -1036,6 +1037,67 @@ srs_error_t srs_av_base64_decode(string cipher, string& plaintext)
|
||||||
return err;
|
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"
|
#define SPACE_CHARS " \t\r\n"
|
||||||
|
|
||||||
int av_toupper(int c)
|
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.
|
// Decode a base64-encoded string.
|
||||||
extern srs_error_t srs_av_base64_decode(std::string cipher, std::string& plaintext);
|
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.
|
// 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)
|
#define SRS_AV_BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1)
|
||||||
|
|
|
@ -2393,6 +2393,89 @@ VOID TEST(KernelUtility, Base64Decode)
|
||||||
EXPECT_TRUE(expect == plaintext);
|
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)
|
VOID TEST(KernelUtility, StringToHex)
|
||||||
{
|
{
|
||||||
if (true) {
|
if (true) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue