BUrl: rework handling of URL encoding
The content of a BUrl should always be in encoded form, to simplify handling and validation. Deprecate the UrlEncode member function and make it private. Instead aadd a new way to handle URL encoding: - All ways to set an URL (constructors, SetUrlString, and all setters) now take an extra boolean parameter indicating if the string is already encoded. The default value is to encode strings automatically. - The static version of UrlEncode and UrlDecode, which operate on a string, are preserved and used by other parts of the API. All unit tests adjusted to handle this, and still passing. Fixes #12983 Change-Id: I06f06978d0d35e56d7c92b67f001856bb7dcafc8 Reviewed-on: https://review.haiku-os.org/c/haiku/+/1193 Reviewed-by: nephele nephele <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
60bb9a9f96
commit
1d242620b4
+28
-10
@@ -66,10 +66,14 @@
|
||||
//! @{
|
||||
|
||||
/*!
|
||||
\fn BUrl::BUrl(const char* url);
|
||||
\fn BUrl::BUrl(const char* url, bool encode = true);
|
||||
\brief Constructs a BUrl and fills it.
|
||||
|
||||
\param url A string to parse and populate the URL fields from.
|
||||
\param encode Wether to urlencode the string.
|
||||
|
||||
The URL fields are extracted from the passed string and encoded. If you are constructing an
|
||||
URL from a string that is already URL-encoded, set encode to false.
|
||||
|
||||
Call InitCheck() to verify that the string was succesfully parsed and
|
||||
resulted in a valid URL.
|
||||
@@ -143,10 +147,13 @@
|
||||
//! @{
|
||||
|
||||
/*!
|
||||
\fn BUrl& BUrl::SetUrlString(const BString& url);
|
||||
\fn BUrl& BUrl::SetUrlString(const BString& url, bool encode = true);
|
||||
\brief Parse a string and set the URL accordingly
|
||||
|
||||
\param url A string to parse as an absolute URL.
|
||||
\param encode Wether to URL-encode the string.
|
||||
|
||||
Set encode to false if the URL string is already URL-encoded.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -225,8 +232,8 @@
|
||||
|
||||
\returns the string representation of the URL.
|
||||
|
||||
A complete URL string is of the form protocol://username:passord\@host:port/path?request#fragment . All the fields are optional, for example a file URL will
|
||||
have only a protocol and a path.
|
||||
A complete URL string is of the form protocol://username:passord\@host:port/path?request#fragment .
|
||||
All the fields are optional, for example a file URL will have only a protocol and a path.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -404,20 +411,31 @@
|
||||
|
||||
|
||||
/*!
|
||||
\fn void BUrl::UrlEncode(bool strict=false)
|
||||
\brief Undocumented public method
|
||||
\fn static BString BUrl::UrlEncode(const BString& url, bool strict=false, bool directory=false)
|
||||
\brief URL-encode a string containing an URL or URL component.
|
||||
|
||||
\param strict Undocumented
|
||||
\param strict Use strict mode
|
||||
\param directory Use directory mode
|
||||
|
||||
In strict mode, space are replaced by %20. In non-strict mode they are replaced by a +
|
||||
character.
|
||||
|
||||
In directory mode, / and \\ characters are not encoded. In the other fields they are
|
||||
percent-encoded.
|
||||
|
||||
\return The encoded URL string
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn void BUrl::UrlDecode(bool strict=false)
|
||||
\brief Undocumented public method
|
||||
\fn static BString BUrl::UrlDecode(const BString& url, bool strict=false)
|
||||
\brief URL-decode a string containing an URL or URL component.
|
||||
|
||||
\param strict Undocumented
|
||||
\param strict Use strict mode.
|
||||
|
||||
\return The decoded URL string
|
||||
|
||||
\since Haiku R1
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
class BUrl : public BArchivable {
|
||||
public:
|
||||
BUrl(const char* url);
|
||||
BUrl(const char* url, bool encode = true);
|
||||
BUrl(BMessage* archive);
|
||||
BUrl(const BUrl& other);
|
||||
BUrl(const BUrl& base, const BString& relative);
|
||||
@@ -23,7 +23,8 @@ public:
|
||||
virtual ~BUrl();
|
||||
|
||||
// URL fields modifiers
|
||||
BUrl& SetUrlString(const BString& url);
|
||||
BUrl& SetUrlString(const BString& url,
|
||||
bool encode = true);
|
||||
BUrl& SetProtocol(const BString& scheme);
|
||||
BUrl& SetUserName(const BString& user);
|
||||
BUrl& SetPassword(const BString& password);
|
||||
@@ -60,10 +61,6 @@ public:
|
||||
bool HasRequest() const;
|
||||
bool HasFragment() const;
|
||||
|
||||
// Url encoding/decoding of needed fields
|
||||
void UrlEncode(bool strict = false);
|
||||
void UrlDecode(bool strict = false);
|
||||
|
||||
status_t IDNAToAscii();
|
||||
status_t IDNAToUnicode();
|
||||
|
||||
@@ -98,6 +95,12 @@ public:
|
||||
operator const char*() const;
|
||||
|
||||
private:
|
||||
// Deprecated methods, use the new constructor with bool parameter
|
||||
explicit BUrl(const char* url);
|
||||
void SetUrlString(const BString& url);
|
||||
void UrlEncode(bool strict = false);
|
||||
void UrlDecode(bool strict = false);
|
||||
|
||||
void _ResetFields();
|
||||
bool _ContainsDelimiter(const BString& url);
|
||||
status_t _ExplodeUrlString(const BString& urlString,
|
||||
|
||||
@@ -44,9 +44,6 @@ BDataRequest::_ProtocolLoop()
|
||||
ssize_t length;
|
||||
bool isBase64 = false;
|
||||
|
||||
// The RFC has examples where some characters are URL-Encoded.
|
||||
fUrl.UrlDecode(true);
|
||||
|
||||
// The RFC says this uses a nonstandard scheme, so the path, query and
|
||||
// fragment are a bit nonsensical. It would be nice to handle them, but
|
||||
// some software (eg. WebKit) relies on data URIs with embedded "#" char
|
||||
|
||||
@@ -25,7 +25,6 @@ BFileRequest::BFileRequest(const BUrl& url, BDataIO* output,
|
||||
BUrlRequest(url, output, listener, context, "BUrlProtocol.File", "file"),
|
||||
fResult()
|
||||
{
|
||||
fUrl.UrlDecode(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -192,7 +192,6 @@ BGopherRequest::BGopherRequest(const BUrl& url, BDataIO* output,
|
||||
{
|
||||
fSocket = new(std::nothrow) BSocket();
|
||||
|
||||
fUrl.UrlDecode();
|
||||
// the first part of the path is actually the document type
|
||||
|
||||
fPath = Url().Path();
|
||||
|
||||
+60
-32
@@ -36,7 +36,7 @@ const uint32 PARSE_NO_MASK_BIT = 0x00000000;
|
||||
const uint32 PARSE_RAW_PATH_MASK_BIT = 0x00000001;
|
||||
|
||||
|
||||
BUrl::BUrl(const char* url)
|
||||
BUrl::BUrl(const char* url, bool encode)
|
||||
:
|
||||
fUrlString(),
|
||||
fProtocol(),
|
||||
@@ -49,7 +49,7 @@ BUrl::BUrl(const char* url)
|
||||
fHasHost(false),
|
||||
fHasFragment(false)
|
||||
{
|
||||
SetUrlString(url);
|
||||
SetUrlString(url, encode);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ BUrl::BUrl(BMessage* archive)
|
||||
BString url;
|
||||
|
||||
if (archive->FindString(kArchivedUrl, &url) == B_OK)
|
||||
SetUrlString(url);
|
||||
SetUrlString(url, false);
|
||||
else
|
||||
_ResetFields();
|
||||
}
|
||||
@@ -206,7 +206,7 @@ BUrl::BUrl(const BPath& path)
|
||||
fHasHost(false),
|
||||
fHasFragment(false)
|
||||
{
|
||||
SetUrlString(UrlEncode(path.Path(), true, true));
|
||||
SetUrlString(path.Path(), true);
|
||||
SetProtocol("file");
|
||||
}
|
||||
|
||||
@@ -220,8 +220,11 @@ BUrl::~BUrl()
|
||||
|
||||
|
||||
BUrl&
|
||||
BUrl::SetUrlString(const BString& url)
|
||||
BUrl::SetUrlString(const BString& url, bool encode)
|
||||
{
|
||||
if (encode)
|
||||
UrlEncode(url, true, true);
|
||||
|
||||
_ExplodeUrlString(url, PARSE_NO_MASK_BIT);
|
||||
return *this;
|
||||
}
|
||||
@@ -611,31 +614,6 @@ BUrl::HasFragment() const
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark URL encoding/decoding of needed fields
|
||||
|
||||
|
||||
void
|
||||
BUrl::UrlEncode(bool strict)
|
||||
{
|
||||
fUser = _DoUrlEncodeChunk(fUser, strict);
|
||||
fPassword = _DoUrlEncodeChunk(fPassword, strict);
|
||||
fHost = _DoUrlEncodeChunk(fHost, strict);
|
||||
fFragment = _DoUrlEncodeChunk(fFragment, strict);
|
||||
fPath = _DoUrlEncodeChunk(fPath, strict, true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BUrl::UrlDecode(bool strict)
|
||||
{
|
||||
fUser = _DoUrlDecodeChunk(fUser, strict);
|
||||
fPassword = _DoUrlDecodeChunk(fPassword, strict);
|
||||
fHost = _DoUrlDecodeChunk(fHost, strict);
|
||||
fFragment = _DoUrlDecodeChunk(fFragment, strict);
|
||||
fPath = _DoUrlDecodeChunk(fPath, strict);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
|
||||
status_t
|
||||
BUrl::IDNAToAscii()
|
||||
@@ -864,7 +842,7 @@ BUrl::operator=(const BUrl& other)
|
||||
const BUrl&
|
||||
BUrl::operator=(const BString& string)
|
||||
{
|
||||
SetUrlString(string);
|
||||
SetUrlString(string, true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -872,7 +850,7 @@ BUrl::operator=(const BString& string)
|
||||
const BUrl&
|
||||
BUrl::operator=(const char* string)
|
||||
{
|
||||
SetUrlString(string);
|
||||
SetUrlString(string, true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1485,3 +1463,53 @@ BUrl::_UrlMimeType() const
|
||||
|
||||
return BString(mime);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark Deprecated methods
|
||||
|
||||
|
||||
BUrl::BUrl(const char* string)
|
||||
:
|
||||
fPort(0),
|
||||
fHasHost(false),
|
||||
fHasFragment(false)
|
||||
{
|
||||
SetUrlString(string, false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BUrl::SetUrlString(const BString& string)
|
||||
{
|
||||
SetUrlString(string, false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BUrl::UrlEncode(bool strict)
|
||||
{
|
||||
fUser = _DoUrlEncodeChunk(fUser, strict, false);
|
||||
fPassword = _DoUrlEncodeChunk(fPassword, strict, false);
|
||||
fHost = _DoUrlEncodeChunk(fHost, strict, false);
|
||||
fFragment = _DoUrlEncodeChunk(fFragment, strict, false);
|
||||
fPath = _DoUrlEncodeChunk(fPath, strict, true);
|
||||
|
||||
fUrlStringValid = false;
|
||||
fAuthorityValid = false;
|
||||
fUserInfoValid = false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BUrl::UrlDecode(bool strict)
|
||||
{
|
||||
fUser = _DoUrlDecodeChunk(fUser, strict);
|
||||
fPassword = _DoUrlDecodeChunk(fPassword, strict);
|
||||
fHost = _DoUrlDecodeChunk(fHost, strict);
|
||||
fFragment = _DoUrlDecodeChunk(fFragment, strict);
|
||||
fPath = _DoUrlDecodeChunk(fPath, strict);
|
||||
|
||||
fUrlStringValid = false;
|
||||
fAuthorityValid = false;
|
||||
fUserInfoValid = false;
|
||||
}
|
||||
|
||||
@@ -537,7 +537,7 @@ UrlTest::RelativeUriTest()
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE(message.String(),
|
||||
BString(tests[index].absolute),
|
||||
BUrl(baseUrl, tests[index].relative).UrlString());
|
||||
BUrl(baseUrl, BString(tests[index].relative)).UrlString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,8 +597,6 @@ UrlTest::IDNTest()
|
||||
NextSubTest();
|
||||
|
||||
BUrl url(tests[i].escaped);
|
||||
url.UrlDecode();
|
||||
|
||||
BUrl idn(tests[i].decoded);
|
||||
status_t success = idn.IDNAToUnicode();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user