Add support for non-URL-compatible parameter parsing (taking + to not mean space, not encoding as such either) and uses it for RTMP auth

This commit is contained in:
Thulinma 2024-06-07 21:06:28 +02:00
parent 8664daeb9a
commit 6eec3661ca
5 changed files with 12 additions and 12 deletions

View file

@ -97,7 +97,7 @@ namespace Encodings{
}
/// urlencodes std::string data, leaving only the characters A-Za-z0-9~!&()' alone.
std::string URL::encode(const std::string &c, const std::string &ign){
std::string URL::encode(const std::string &c, const std::string &ign, bool queryStr){
std::string escaped = "";
int max = c.length();
for (int i = 0; i < max; i++){
@ -107,7 +107,7 @@ namespace Encodings{
(ign.size() && ign.find(c[i]) != std::string::npos)){
escaped.append(&c[i], 1);
}else{
if (c[i] == ' '){
if (c[i] == ' ' && queryStr){
escaped.append("+");
}else{
escaped.append("%");
@ -119,7 +119,7 @@ namespace Encodings{
}
/// urldecodes std::string data, parsing out both %-encoded characters and +-encoded spaces.
std::string URL::decode(const std::string &in){
std::string URL::decode(const std::string &in, bool queryStr){
std::string out;
for (unsigned int i = 0; i < in.length(); ++i){
if (in[i] == '%'){
@ -130,7 +130,7 @@ namespace Encodings{
if (i < in.length()){tmp += Hex::ord(in[i]);}
out += tmp;
}else{
if (in[i] == '+'){
if (in[i] == '+' && queryStr){
out += ' ';
}else{
out += in[i];

View file

@ -19,9 +19,9 @@ namespace Encodings{
class URL{
public:
/// urldecodes std::string data, parsing out both %-encoded characters and +-encoded spaces.
static std::string decode(const std::string &in);
static std::string decode(const std::string &in, bool queryStr = false);
/// urlencodes std::string data, leaving only the characters A-Za-z0-9~!&()' alone.
static std::string encode(const std::string &c, const std::string &ign = "");
static std::string encode(const std::string &c, const std::string &ign = "", bool queryStr = false);
};
/// Hexadecimal-related functions

View file

@ -756,7 +756,7 @@ bool HTTP::Parser::parse(std::string &HTTPbuffer, Util::DataCallback &cb){
/// HTTP variable parser to std::map<std::string, std::string> structure.
/// Reads variables from data, decodes and stores them to storage.
void HTTP::parseVars(const std::string &data, std::map<std::string, std::string> &storage, const std::string & separator){
void HTTP::parseVars(const std::string &data, std::map<std::string, std::string> &storage, const std::string & separator, bool queryStr){
std::string varname;
std::string varval;
// position where a part starts (e.g. after &)
@ -776,7 +776,7 @@ void HTTP::parseVars(const std::string &data, std::map<std::string, std::string>
}
if (varname.size()){
DONTEVEN_MSG("Found key:value pair '%s:%s'", varname.c_str(), varval.c_str());
storage[Encodings::URL::decode(varname)] = Encodings::URL::decode(varval);
storage[Encodings::URL::decode(varname, queryStr)] = Encodings::URL::decode(varval, queryStr);
}
if (nextpos == std::string::npos){
// in case the string is gigantic

View file

@ -14,7 +14,7 @@ namespace HTTP{
/// HTTP variable parser to std::map<std::string, std::string> structure.
/// Reads variables from data, decodes and stores them to storage.
void parseVars(const std::string &data, std::map<std::string, std::string> &storage, const std::string & separator = "&");
void parseVars(const std::string &data, std::map<std::string, std::string> &storage, const std::string & separator = "&", bool queryStr = true);
/// Simple class for reading and writing HTTP 1.0 and 1.1.
class Parser{

View file

@ -1483,7 +1483,7 @@ namespace Mist{
}
if (description.find("?reason=needauth") != std::string::npos){
std::map<std::string, std::string> authVars;
HTTP::parseVars(description.substr(description.find("?reason=needauth") + 1), authVars);
HTTP::parseVars(description.substr(description.find("?reason=needauth") + 1), authVars, "&", false);
std::string authSalt = authVars.count("salt") ? authVars["salt"] : "";
std::string authOpaque = authVars.count("opaque") ? authVars["opaque"] : "";
std::string authChallenge = authVars.count("challenge") ? authVars["challenge"] : "";
@ -1504,9 +1504,9 @@ namespace Mist{
}
Secure::md5bin(to_hash.data(), to_hash.size(), md5buffer);
std::string hash_two = Encodings::Base64::encode(std::string(md5buffer, 16));
std::string authStr = "?authmod=adobe&user=" + Encodings::URL::encode(pushUrl.user, "/:=@[]") +
std::string authStr = "?authmod=adobe&user=" + Encodings::URL::encode(pushUrl.user, "/:=@[]+ ") +
"&challenge=00000000&response=" + hash_two;
if (authOpaque.size()){authStr += "&opaque=" + Encodings::URL::encode(authOpaque, "/:=@[]");}
if (authOpaque.size()){authStr += "&opaque=" + Encodings::URL::encode(authOpaque, "/:=@[]+ ");}
startPushOut(authStr.c_str());
return;
}