mirror of
https://github.com/ossrs/srs.git
synced 2025-02-12 11:21:52 +00:00
Replace base64 to match MIT license. 3.0.32
This commit is contained in:
parent
0a63448b86
commit
84f81983aa
7 changed files with 117 additions and 235 deletions
|
@ -184,6 +184,7 @@ Please select according to languages:
|
|||
|
||||
### V3 changes
|
||||
|
||||
* v3.0, 2018-07-22, Replace base64 to match MIT license. 3.0.32
|
||||
* v3.0, 2018-07-22, Replace crc32 IEEE and MPEG by pycrc to match MIT license. 3.0.31
|
||||
* v3.0, 2018-07-21, Replace crc32 IEEE by golang to match MIT license. 3.0.30
|
||||
* v3.0, 2018-02-16, Fix [#464][bug #464], support RTMP origin cluster. 3.0.29
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
// current release version
|
||||
#define VERSION_MAJOR 3
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 31
|
||||
#define VERSION_REVISION 32
|
||||
|
||||
// generated by configure, only macros.
|
||||
#include <srs_auto_headers.hpp>
|
||||
|
|
|
@ -318,6 +318,7 @@
|
|||
#define ERROR_KAFKA_CODEC_MESSAGE 4036
|
||||
#define ERROR_KAFKA_CODEC_PRODUCER 4037
|
||||
#define ERROR_HTTP_302_INVALID 4038
|
||||
#define ERROR_BASE64_DECODE 4039
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// HTTP API error.
|
||||
|
|
|
@ -830,217 +830,113 @@ 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef UINT_MAX
|
||||
#define UINT_MAX 0xffffffff
|
||||
#endif
|
||||
|
||||
#ifndef AV_RB32
|
||||
# define AV_RB32(x) \
|
||||
(((uint32_t)((const uint8_t*)(x))[0] << 24) | \
|
||||
(((const uint8_t*)(x))[1] << 16) | \
|
||||
(((const uint8_t*)(x))[2] << 8) | \
|
||||
((const uint8_t*)(x))[3])
|
||||
#endif
|
||||
|
||||
#ifndef AV_WL32
|
||||
# define AV_WL32(p, darg) do { \
|
||||
unsigned d = (darg); \
|
||||
((uint8_t*)(p))[0] = (d); \
|
||||
((uint8_t*)(p))[1] = (d)>>8; \
|
||||
((uint8_t*)(p))[2] = (d)>>16; \
|
||||
((uint8_t*)(p))[3] = (d)>>24; \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
# define AV_WN(s, p, v) AV_WL##s(p, v)
|
||||
|
||||
# if defined(AV_WN32) && !defined(AV_WL32)
|
||||
# define AV_WL32(p, v) AV_WN32(p, v)
|
||||
# elif !defined(AV_WN32) && defined(AV_WL32)
|
||||
# define AV_WN32(p, v) AV_WL32(p, v)
|
||||
# endif
|
||||
|
||||
#ifndef AV_WN32
|
||||
# define AV_WN32(p, v) AV_WN(32, p, v)
|
||||
#endif
|
||||
|
||||
#define AV_BSWAP16C(x) (((x) << 8 & 0xff00) | ((x) >> 8 & 0x00ff))
|
||||
#define AV_BSWAP32C(x) (AV_BSWAP16C(x) << 16 | AV_BSWAP16C((x) >> 16))
|
||||
|
||||
#ifndef av_bswap32
|
||||
static const uint32_t av_bswap32(uint32_t x)
|
||||
// @see golang encoding/base64/base64.go
|
||||
srs_error_t srs_av_base64_decode(string cipher, string& plaintext)
|
||||
{
|
||||
return AV_BSWAP32C(x);
|
||||
}
|
||||
#endif
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
#define av_be2ne32(x) av_bswap32(x)
|
||||
/**
|
||||
* @file
|
||||
* @brief Base64 encode/decode
|
||||
* @author Ryan Martell <rdm4@martellventures.com> (with lots of Michael)
|
||||
*/
|
||||
|
||||
/* ---------------- private code */
|
||||
static const uint8_t map2[256] =
|
||||
{
|
||||
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff,
|
||||
// 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+/";
|
||||
|
||||
0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
|
||||
0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
|
||||
0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x01,
|
||||
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
||||
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
|
||||
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b,
|
||||
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
|
||||
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
|
||||
0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
|
||||
uint8_t decodeMap[256];
|
||||
memset(decodeMap, 0xff, sizeof(decodeMap));
|
||||
|
||||
0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
|
||||
#define BASE64_DEC_STEP(i) do { \
|
||||
bits = map2[in[i]]; \
|
||||
if (bits & 0x80) \
|
||||
goto out ## i; \
|
||||
v = i ? (v << 6) + bits : bits; \
|
||||
} while(0)
|
||||
|
||||
int srs_av_base64_decode(uint8_t* out, const char* in_str, int out_size)
|
||||
{
|
||||
uint8_t *dst = out;
|
||||
uint8_t *end = out + out_size;
|
||||
// no sign extension
|
||||
const uint8_t *in = (const uint8_t*)in_str;
|
||||
unsigned bits = 0xff;
|
||||
unsigned v = 0;
|
||||
|
||||
while (end - dst > 3) {
|
||||
BASE64_DEC_STEP(0);
|
||||
BASE64_DEC_STEP(1);
|
||||
BASE64_DEC_STEP(2);
|
||||
BASE64_DEC_STEP(3);
|
||||
// Using AV_WB32 directly confuses compiler
|
||||
v = av_be2ne32(v << 8);
|
||||
AV_WN32(dst, v);
|
||||
dst += 3;
|
||||
in += 4;
|
||||
}
|
||||
if (end - dst) {
|
||||
BASE64_DEC_STEP(0);
|
||||
BASE64_DEC_STEP(1);
|
||||
BASE64_DEC_STEP(2);
|
||||
BASE64_DEC_STEP(3);
|
||||
*dst++ = v >> 16;
|
||||
if (end - dst)
|
||||
*dst++ = v >> 8;
|
||||
if (end - dst)
|
||||
*dst++ = v;
|
||||
in += 4;
|
||||
}
|
||||
while (1) {
|
||||
BASE64_DEC_STEP(0);
|
||||
in++;
|
||||
BASE64_DEC_STEP(0);
|
||||
in++;
|
||||
BASE64_DEC_STEP(0);
|
||||
in++;
|
||||
BASE64_DEC_STEP(0);
|
||||
in++;
|
||||
for (int i = 0; i < encoder.length(); i++) {
|
||||
decodeMap[(uint8_t)encoder.at(i)] = uint8_t(i);
|
||||
}
|
||||
|
||||
out3:
|
||||
*dst++ = v >> 10;
|
||||
v <<= 2;
|
||||
out2:
|
||||
*dst++ = v >> 4;
|
||||
out1:
|
||||
out0:
|
||||
return bits & 1 ? -1 : (int)(dst - out);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* b64_encode: Stolen from VLC's http.c.
|
||||
* Simplified by Michael.
|
||||
* Fixed edge cases and made it work from data (vs. strings) by Ryan.
|
||||
*****************************************************************************/
|
||||
char* srs_av_base64_encode(char* out, int out_size, const uint8_t* in, int in_size)
|
||||
{
|
||||
static const char b64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
char *ret, *dst;
|
||||
unsigned i_bits = 0;
|
||||
int i_shift = 0;
|
||||
int bytes_remaining = in_size;
|
||||
// decode is like Decode but returns an additional 'end' value, which
|
||||
// indicates if end-of-message padding or a partial quantum was encountered
|
||||
// and thus any additional data is an error.
|
||||
int si = 0;
|
||||
|
||||
if (in_size >= (int)(UINT_MAX / 4) ||
|
||||
out_size < SRS_AV_BASE64_SIZE(in_size))
|
||||
return NULL;
|
||||
ret = dst = out;
|
||||
while (bytes_remaining > 3) {
|
||||
i_bits = AV_RB32(in);
|
||||
in += 3; bytes_remaining -= 3;
|
||||
*dst++ = b64[ i_bits>>26 ];
|
||||
*dst++ = b64[(i_bits>>20) & 0x3F];
|
||||
*dst++ = b64[(i_bits>>14) & 0x3F];
|
||||
*dst++ = b64[(i_bits>>8 ) & 0x3F];
|
||||
// skip over newlines
|
||||
for (; si < cipher.length() && (cipher.at(si) == '\n' || cipher.at(si) == '\r'); si++) {
|
||||
}
|
||||
i_bits = 0;
|
||||
while (bytes_remaining) {
|
||||
i_bits = (i_bits << 8) + *in++;
|
||||
bytes_remaining--;
|
||||
i_shift += 8;
|
||||
}
|
||||
while (i_shift > 0) {
|
||||
*dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
|
||||
i_shift -= 6;
|
||||
}
|
||||
while ((dst - ret) & 3)
|
||||
*dst++ = '=';
|
||||
*dst = '\0';
|
||||
|
||||
return ret;
|
||||
for (bool end = false; si < cipher.length() && !end;) {
|
||||
// Decode quantum using the base64 alphabet
|
||||
uint8_t dbuf[4];
|
||||
memset(dbuf, 0x00, sizeof(dbuf));
|
||||
|
||||
int dinc = 3;
|
||||
int dlen = 4;
|
||||
|
||||
for (int j = 0; j < sizeof(dbuf); j++) {
|
||||
if (si == cipher.length()) {
|
||||
if (padding != -1 || j < 2) {
|
||||
return srs_error_new(ERROR_BASE64_DECODE, "corrupt input at %d", si);
|
||||
}
|
||||
|
||||
dinc = j - 1;
|
||||
dlen = j;
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
|
||||
char in = cipher.at(si);
|
||||
|
||||
si++;
|
||||
// skip over newlines
|
||||
for (; si < cipher.length() && (cipher.at(si) == '\n' || cipher.at(si) == '\r'); si++) {
|
||||
}
|
||||
|
||||
if (in == padding) {
|
||||
// We've reached the end and there's padding
|
||||
switch (j) {
|
||||
case 0:
|
||||
case 1:
|
||||
// incorrect padding
|
||||
return srs_error_new(ERROR_BASE64_DECODE, "corrupt input at %d", si);
|
||||
case 2:
|
||||
// "==" is expected, the first "=" is already consumed.
|
||||
if (si == cipher.length()) {
|
||||
return srs_error_new(ERROR_BASE64_DECODE, "corrupt input at %d", si);
|
||||
}
|
||||
if (cipher.at(si) != padding) {
|
||||
// incorrect padding
|
||||
return srs_error_new(ERROR_BASE64_DECODE, "corrupt input at %d", si);
|
||||
}
|
||||
|
||||
si++;
|
||||
// skip over newlines
|
||||
for (; si < cipher.length() && (cipher.at(si) == '\n' || cipher.at(si) == '\r'); si++) {
|
||||
}
|
||||
}
|
||||
|
||||
if (si < cipher.length()) {
|
||||
// trailing garbage
|
||||
err = srs_error_new(ERROR_BASE64_DECODE, "corrupt input at %d", si);
|
||||
}
|
||||
dinc = 3;
|
||||
dlen = j;
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
|
||||
dbuf[j] = decodeMap[(uint8_t)in];
|
||||
if (dbuf[j] == 0xff) {
|
||||
return srs_error_new(ERROR_BASE64_DECODE, "corrupt input at %d", si);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert 4x 6bit source bytes into 3 bytes
|
||||
uint32_t val = uint32_t(dbuf[0])<<18 | uint32_t(dbuf[1])<<12 | uint32_t(dbuf[2])<<6 | uint32_t(dbuf[3]);
|
||||
if (dlen >= 2) {
|
||||
plaintext.append(1, char(val >> 16));
|
||||
}
|
||||
if (dlen >= 3) {
|
||||
plaintext.append(1, char(val >> 8));
|
||||
}
|
||||
if (dlen >= 4) {
|
||||
plaintext.append(1, char(val));
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#define SPACE_CHARS " \t\r\n"
|
||||
|
|
|
@ -147,27 +147,8 @@ extern uint32_t srs_crc32_ieee(const void* buf, int size, uint32_t previous = 0)
|
|||
|
||||
/**
|
||||
* Decode a base64-encoded string.
|
||||
*
|
||||
* @param out buffer for decoded data
|
||||
* @param in null-terminated input string
|
||||
* @param out_size size in bytes of the out buffer, must be at
|
||||
* least 3/4 of the length of in
|
||||
* @return number of bytes written, or a negative value in case of
|
||||
* invalid input
|
||||
*/
|
||||
extern int srs_av_base64_decode(uint8_t* out, const char* in, int out_size);
|
||||
|
||||
/**
|
||||
* Encode data to base64 and null-terminate.
|
||||
*
|
||||
* @param out buffer for encoded data
|
||||
* @param out_size size in bytes of the out buffer (including the
|
||||
* null terminator), must be at least AV_BASE64_SIZE(in_size)
|
||||
* @param in input buffer containing the data to encode
|
||||
* @param in_size size in bytes of the in buffer
|
||||
* @return out or NULL in case of error
|
||||
*/
|
||||
extern char* srs_av_base64_encode(char* out, int out_size, const uint8_t* in, int in_size);
|
||||
extern srs_error_t srs_av_base64_decode(std::string cipher, std::string& plaintext);
|
||||
|
||||
/**
|
||||
* Calculate the output size needed to base64-encode x bytes to a
|
||||
|
|
|
@ -583,23 +583,16 @@ srs_error_t SrsRtspSdp::parse_control_attribute(string attr)
|
|||
return err;
|
||||
}
|
||||
|
||||
string SrsRtspSdp::base64_decode(string value)
|
||||
string SrsRtspSdp::base64_decode(string cipher)
|
||||
{
|
||||
if (value.empty()) {
|
||||
if (cipher.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int nb_output = (int)(value.length() * 2);
|
||||
uint8_t* output = new uint8_t[nb_output];
|
||||
SrsAutoFreeA(uint8_t, output);
|
||||
string plaintext;
|
||||
srs_error_t err = srs_av_base64_decode(cipher, plaintext);
|
||||
srs_freep(err);
|
||||
|
||||
int ret = srs_av_base64_decode(output, (char*)value.c_str(), nb_output);
|
||||
if (ret <= 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string plaintext;
|
||||
plaintext.append((char*)output, ret);
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
|
|
|
@ -1674,5 +1674,15 @@ VOID TEST(KernelUtility, CRC32MPEGTS)
|
|||
}
|
||||
}
|
||||
|
||||
VOID TEST(KernelUtility, Base64Decode)
|
||||
{
|
||||
string cipher = "dXNlcjpwYXNzd29yZA==";
|
||||
string expect = "user:password";
|
||||
|
||||
string plaintext;
|
||||
EXPECT_TRUE(srs_success == srs_av_base64_decode(cipher, plaintext));
|
||||
EXPECT_TRUE(expect == plaintext);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue