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. /// 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 = ""; std::string escaped = "";
int max = c.length(); int max = c.length();
for (int i = 0; i < max; i++){ for (int i = 0; i < max; i++){
@ -107,7 +107,7 @@ namespace Encodings{
(ign.size() && ign.find(c[i]) != std::string::npos)){ (ign.size() && ign.find(c[i]) != std::string::npos)){
escaped.append(&c[i], 1); escaped.append(&c[i], 1);
}else{ }else{
if (c[i] == ' '){ if (c[i] == ' ' && queryStr){
escaped.append("+"); escaped.append("+");
}else{ }else{
escaped.append("%"); escaped.append("%");
@ -119,7 +119,7 @@ namespace Encodings{
} }
/// urldecodes std::string data, parsing out both %-encoded characters and +-encoded spaces. /// 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; std::string out;
for (unsigned int i = 0; i < in.length(); ++i){ for (unsigned int i = 0; i < in.length(); ++i){
if (in[i] == '%'){ if (in[i] == '%'){
@ -130,7 +130,7 @@ namespace Encodings{
if (i < in.length()){tmp += Hex::ord(in[i]);} if (i < in.length()){tmp += Hex::ord(in[i]);}
out += tmp; out += tmp;
}else{ }else{
if (in[i] == '+'){ if (in[i] == '+' && queryStr){
out += ' '; out += ' ';
}else{ }else{
out += in[i]; out += in[i];

View file

@ -19,9 +19,9 @@ namespace Encodings{
class URL{ class URL{
public: public:
/// urldecodes std::string data, parsing out both %-encoded characters and +-encoded spaces. /// 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. /// 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 /// 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. /// HTTP variable parser to std::map<std::string, std::string> structure.
/// Reads variables from data, decodes and stores them to storage. /// 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 varname;
std::string varval; std::string varval;
// position where a part starts (e.g. after &) // 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()){ if (varname.size()){
DONTEVEN_MSG("Found key:value pair '%s:%s'", varname.c_str(), varval.c_str()); 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){ if (nextpos == std::string::npos){
// in case the string is gigantic // 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. /// HTTP variable parser to std::map<std::string, std::string> structure.
/// Reads variables from data, decodes and stores them to storage. /// 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. /// Simple class for reading and writing HTTP 1.0 and 1.1.
class Parser{ class Parser{

View file

@ -1483,7 +1483,7 @@ namespace Mist{
} }
if (description.find("?reason=needauth") != std::string::npos){ if (description.find("?reason=needauth") != std::string::npos){
std::map<std::string, std::string> authVars; 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 authSalt = authVars.count("salt") ? authVars["salt"] : "";
std::string authOpaque = authVars.count("opaque") ? authVars["opaque"] : ""; std::string authOpaque = authVars.count("opaque") ? authVars["opaque"] : "";
std::string authChallenge = authVars.count("challenge") ? authVars["challenge"] : ""; std::string authChallenge = authVars.count("challenge") ? authVars["challenge"] : "";
@ -1504,9 +1504,9 @@ namespace Mist{
} }
Secure::md5bin(to_hash.data(), to_hash.size(), md5buffer); Secure::md5bin(to_hash.data(), to_hash.size(), md5buffer);
std::string hash_two = Encodings::Base64::encode(std::string(md5buffer, 16)); 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; "&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()); startPushOut(authStr.c_str());
return; return;
} }