Add wxURI::SetUserAndPassword()

This allows to set the user info part of the user name without escaping
the username and password manually in the application.
This commit is contained in:
Vadim Zeitlin
2025-03-14 19:11:17 +01:00
parent 33aac81380
commit f19735beff
4 changed files with 82 additions and 7 deletions
+5
View File
@@ -98,6 +98,11 @@ public:
wxString GetUser() const;
wxString GetPassword() const;
// Set username and password for the URI. This function is _not_ the exact
// counterpart of GetUserInfo() because it takes unescaped strings, unlike
// the latter, which returns them in the escaped form, hence it uses a
// deliberately different name.
void SetUserAndPassword(const wxString& user, const wxString& password = {});
// combine all URI components into a single string
//
+20
View File
@@ -286,6 +286,26 @@ public:
*/
void Resolve(const wxURI& base, int flags = wxURI_STRICT);
/**
Sets the user and password for the URI.
Please note that this function is not the exact counterpart of
GetUserInfo() because it takes unescaped strings, unlike the latter,
which returns them in the escaped form, and hence it uses a slightly
different name. For example, passing `user@domain` as @a user to this
function will result in GetUser() returning `user%40domain` (which can
be turned back into the original string by passing it to Unescape()).
@param user
User name. If empty, resets any existing user information.
@param password
Password. If empty, the password is not set (and any existing
password is removed).
@since 3.3.0
*/
void SetUserAndPassword(const wxString& user, const wxString& password = {});
/**
Translates all escape sequences (normal characters and returns the result.
+48 -7
View File
@@ -120,6 +120,15 @@ wxString wxURI::Unescape(const wxString& uri)
return wxString::FromUTF8(buf);
}
static void AppendEscaped(wxString& s, char c)
{
static const char* hexDigits = "0123456789abcdef";
s += '%';
s += hexDigits[(c >> 4) & 15];
s += hexDigits[c & 15];
}
void wxURI::AppendNextEscaped(wxString& s, const char *& p)
{
// check for an already encoded character:
@@ -133,13 +142,7 @@ void wxURI::AppendNextEscaped(wxString& s, const char *& p)
}
else // really needs escaping
{
static const char* hexDigits = "0123456789abcdef";
const char c = *p++;
s += '%';
s += hexDigits[(c >> 4) & 15];
s += hexDigits[c & 15];
AppendEscaped(s, *p++);
}
}
@@ -166,6 +169,44 @@ wxString wxURI::GetPassword() const
return m_userinfo(posColon + 1, wxString::npos);
}
void wxURI::SetUserAndPassword(const wxString& user, const wxString& password)
{
if ( user.empty() )
{
m_userinfo.clear();
m_fields &= ~wxURI_USERINFO;
return;
}
m_fields |= wxURI_USERINFO;
auto escapeAsUserInfo = [](const wxString& in)
{
wxString out;
out.reserve(in.length());
for ( auto c : in.utf8_string() )
{
// We could allow unencoded colon in the password (only), but it
// doesn't seem to be worth the trouble, so always encode it in
// both the username (where it has to be done) and the password.
if ( IsUnreserved(c) || IsSubDelim(c) )
out += c;
else
AppendEscaped(out, c);
}
return out;
};
m_userinfo = escapeAsUserInfo(user);
if ( !password.empty() )
{
m_userinfo += ':';
m_userinfo += escapeAsUserInfo(password);
}
}
// combine all URI fields in a single string, applying funcDecode to each
// component which it may make sense to decode (i.e. "unescape")
wxString wxURI::DoBuildURI(wxString (*funcDecode)(const wxString&)) const
+9
View File
@@ -321,6 +321,15 @@ TEST_CASE("URI::UserInfo", "[uri]")
CHECK( uri.Create("https://u:pass%3Dword@h/") );
CHECK( wxURI::Unescape(uri.GetPassword()) == "pass=word" );
// Also test that using SetUserAndPassword() works.
uri = "https://host/";
uri.SetUserAndPassword("me@here!");
CHECK( uri.BuildURI() == "https://me%40here!@host/" );
uri.SetUserAndPassword("you:", "?me");
INFO(DumpURI(uri));
CHECK( uri.BuildURI() == "https://you%3a:%3fme@host/" );
}
//examples taken from RFC 2396.bis