From 6eec3661ca7fe1abd4b87a33504eefe7fb6e6898 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Fri, 7 Jun 2024 21:06:28 +0200 Subject: [PATCH] Add support for non-URL-compatible parameter parsing (taking + to not mean space, not encoding as such either) and uses it for RTMP auth --- lib/encode.cpp | 8 ++++---- lib/encode.h | 4 ++-- lib/http_parser.cpp | 4 ++-- lib/http_parser.h | 2 +- src/output/output_rtmp.cpp | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/encode.cpp b/lib/encode.cpp index e2cda294..88691630 100644 --- a/lib/encode.cpp +++ b/lib/encode.cpp @@ -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]; diff --git a/lib/encode.h b/lib/encode.h index d20ecf50..224727d7 100644 --- a/lib/encode.h +++ b/lib/encode.h @@ -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 diff --git a/lib/http_parser.cpp b/lib/http_parser.cpp index c33a1297..44f5ed20 100644 --- a/lib/http_parser.cpp +++ b/lib/http_parser.cpp @@ -756,7 +756,7 @@ bool HTTP::Parser::parse(std::string &HTTPbuffer, Util::DataCallback &cb){ /// HTTP variable parser to std::map structure. /// Reads variables from data, decodes and stores them to storage. -void HTTP::parseVars(const std::string &data, std::map &storage, const std::string & separator){ +void HTTP::parseVars(const std::string &data, std::map &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 } 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 diff --git a/lib/http_parser.h b/lib/http_parser.h index b45aedb9..82879180 100644 --- a/lib/http_parser.h +++ b/lib/http_parser.h @@ -14,7 +14,7 @@ namespace HTTP{ /// HTTP variable parser to std::map structure. /// Reads variables from data, decodes and stores them to storage. - void parseVars(const std::string &data, std::map &storage, const std::string & separator = "&"); + void parseVars(const std::string &data, std::map &storage, const std::string & separator = "&", bool queryStr = true); /// Simple class for reading and writing HTTP 1.0 and 1.1. class Parser{ diff --git a/src/output/output_rtmp.cpp b/src/output/output_rtmp.cpp index ceadfa91..17dc0f9c 100644 --- a/src/output/output_rtmp.cpp +++ b/src/output/output_rtmp.cpp @@ -1483,7 +1483,7 @@ namespace Mist{ } if (description.find("?reason=needauth") != std::string::npos){ std::map 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; }