Browse Source

Tweaked URL::addEscapeChars() to make its character substitutions more compliant with RFC3986

tags/2021-05-28
jules 7 years ago
parent
commit
23cdad6a80
2 changed files with 38 additions and 52 deletions
  1. +26
    -28
      modules/juce_core/network/juce_URL.cpp
  2. +12
    -24
      modules/juce_core/network/juce_URL.h

+ 26
- 28
modules/juce_core/network/juce_URL.cpp View File

@@ -130,7 +130,7 @@ URL::DownloadTask* URL::DownloadTask::createFallbackDownloader (const URL& urlTo
return nullptr;
}
URL::DownloadTask::DownloadTask() : contentLength (-1), downloaded (0), finished (false), error (false), httpCode (-1) {}
URL::DownloadTask::DownloadTask() {}
URL::DownloadTask::~DownloadTask() {}
//==============================================================================
@@ -250,6 +250,7 @@ namespace URLHelpers
static int findStartOfNetLocation (const String& url)
{
int start = findEndOfScheme (url);
while (url[start] == '/')
++start;
@@ -305,8 +306,8 @@ String URL::getDomain() const
const int end2 = url.indexOfChar (start, ':');
const int end = (end1 < 0 && end2 < 0) ? std::numeric_limits<int>::max()
: ((end1 < 0 || end2 < 0) ? jmax (end1, end2)
: jmin (end1, end2));
: ((end1 < 0 || end2 < 0) ? jmax (end1, end2)
: jmin (end1, end2));
return url.substring (start, end);
}
@@ -325,7 +326,7 @@ String URL::getScheme() const
int URL::getPort() const
{
const int colonPos = url.indexOfChar (URLHelpers::findStartOfNetLocation (url), ':');
auto colonPos = url.indexOfChar (URLHelpers::findStartOfNetLocation (url), ':');
return colonPos > 0 ? url.substring (colonPos + 1).getIntValue() : 0;
}
@@ -366,7 +367,7 @@ void URL::createHeadersAndPostData (String& headers, MemoryBlock& postDataToWrit
// (this doesn't currently support mixing custom post-data with uploads..)
jassert (postData.getSize() == 0);
const String boundary (String::toHexString (Random::getSystemRandom().nextInt64()));
auto boundary = String::toHexString (Random::getSystemRandom().nextInt64());
headers << "Content-Type: multipart/form-data; boundary=" << boundary << "\r\n";
@@ -379,22 +380,20 @@ void URL::createHeadersAndPostData (String& headers, MemoryBlock& postDataToWrit
<< "\r\n--" << boundary;
}
for (int i = 0; i < filesToUpload.size(); ++i)
for (auto* f : filesToUpload)
{
const Upload& f = *filesToUpload.getObjectPointerUnchecked(i);
data << "\r\nContent-Disposition: form-data; name=\"" << f.parameterName
<< "\"; filename=\"" << f.filename << "\"\r\n";
data << "\r\nContent-Disposition: form-data; name=\"" << f->parameterName
<< "\"; filename=\"" << f->filename << "\"\r\n";
if (f.mimeType.isNotEmpty())
data << "Content-Type: " << f.mimeType << "\r\n";
if (f->mimeType.isNotEmpty())
data << "Content-Type: " << f->mimeType << "\r\n";
data << "Content-Transfer-Encoding: binary\r\n\r\n";
if (f.data != nullptr)
data << *f.data;
if (f->data != nullptr)
data << *f->data;
else
data << f.file;
data << f->file;
data << "\r\n--" << boundary;
}
@@ -419,8 +418,8 @@ bool URL::isProbablyAWebsiteURL (const String& possibleURL)
{
static const char* validProtocols[] = { "http:", "ftp:", "https:" };
for (int i = 0; i < numElementsInArray (validProtocols); ++i)
if (possibleURL.startsWithIgnoreCase (validProtocols[i]))
for (auto* protocol : validProtocols)
if (possibleURL.startsWithIgnoreCase (protocol))
return true;
if (possibleURL.containsChar ('@')
@@ -435,7 +434,7 @@ bool URL::isProbablyAWebsiteURL (const String& possibleURL)
bool URL::isProbablyAnEmailAddress (const String& possibleEmailAddress)
{
const int atSign = possibleEmailAddress.indexOfChar ('@');
auto atSign = possibleEmailAddress.indexOfChar ('@');
return atSign > 0
&& possibleEmailAddress.lastIndexOfChar ('.') > (atSign + 1)
@@ -504,8 +503,7 @@ WebInputStream* URL::createInputStream (const bool usePostCommand,
}
//==============================================================================
bool URL::readEntireBinaryStream (MemoryBlock& destData,
const bool usePostCommand) const
bool URL::readEntireBinaryStream (MemoryBlock& destData, bool usePostCommand) const
{
const ScopedPointer<InputStream> in (createInputStream (usePostCommand));
@@ -518,7 +516,7 @@ bool URL::readEntireBinaryStream (MemoryBlock& destData,
return false;
}
String URL::readEntireTextStream (const bool usePostCommand) const
String URL::readEntireTextStream (bool usePostCommand) const
{
const ScopedPointer<InputStream> in (createInputStream (usePostCommand));
@@ -528,7 +526,7 @@ String URL::readEntireTextStream (const bool usePostCommand) const
return {};
}
XmlElement* URL::readEntireXmlStream (const bool usePostCommand) const
XmlElement* URL::readEntireXmlStream (bool usePostCommand) const
{
return XmlDocument::parse (readEntireTextStream (usePostCommand));
}
@@ -601,7 +599,7 @@ URL URL::withDataToUpload (const String& parameterName, const String& filename,
//==============================================================================
String URL::removeEscapeChars (const String& s)
{
String result (s.replaceCharacter ('+', ' '));
auto result = s.replaceCharacter ('+', ' ');
if (! result.containsChar ('%'))
return result;
@@ -628,9 +626,9 @@ String URL::removeEscapeChars (const String& s)
return String::fromUTF8 (utf8.getRawDataPointer(), utf8.size());
}
String URL::addEscapeChars (const String& s, const bool isParameter, bool roundBracketsAreLegal)
String URL::addEscapeChars (const String& s, bool isParameter, bool roundBracketsAreLegal)
{
String legalChars (isParameter ? "_-.*!'"
String legalChars (isParameter ? "_-.~"
: ",$_-.*!'");
if (roundBracketsAreLegal)
@@ -640,7 +638,7 @@ String URL::addEscapeChars (const String& s, const bool isParameter, bool roundB
for (int i = 0; i < utf8.size(); ++i)
{
const char c = utf8.getUnchecked(i);
auto c = utf8.getUnchecked(i);
if (! (CharacterFunctions::isLetterOrDigit (c)
|| legalChars.containsChar ((juce_wchar) c)))
@@ -657,12 +655,12 @@ String URL::addEscapeChars (const String& s, const bool isParameter, bool roundB
//==============================================================================
bool URL::launchInDefaultBrowser() const
{
String u (toString (true));
auto u = toString (true);
if (u.containsChar ('@') && ! u.containsChar (':'))
u = "mailto:" + u;
return Process::openDocument (u, String());
return Process::openDocument (u, {});
}
} // namespace juce

+ 12
- 24
modules/juce_core/network/juce_URL.h View File

@@ -47,13 +47,13 @@ public:
URL (const String& url);
/** Creates a copy of another URL. */
URL (const URL& other);
URL (const URL&);
/** Destructor. */
~URL();
/** Copies this URL from another one. */
URL& operator= (const URL& other);
URL& operator= (const URL&);
/** Compares two URLs.
All aspects of the URLs must be identical for them to match, including any parameters,
@@ -78,19 +78,16 @@ public:
bool isWellFormed() const;
/** Returns just the domain part of the URL.
E.g. for "http://www.xyz.com/foobar", this will return "www.xyz.com".
*/
String getDomain() const;
/** Returns the path part of the URL.
E.g. for "http://www.xyz.com/foo/bar?x=1", this will return "foo/bar".
*/
String getSubPath() const;
/** Returns the scheme of the URL.
E.g. for "http://www.xyz.com/foobar", this will return "http". (It won't
include the colon).
*/
@@ -102,7 +99,6 @@ public:
int getPort() const;
/** Returns a new version of this URL with a different domain and path.
E.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with
"abc.com/zzz", it'll return "http://abc.com/zzz?x=1".
@see withNewSubPath
@@ -110,7 +106,6 @@ public:
URL withNewDomainAndPath (const String& newFullPath) const;
/** Returns a new version of this URL with a different sub-path.
E.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with
"bar", it'll return "http://www.xyz.com/bar?x=1".
@see withNewDomainAndPath
@@ -118,7 +113,6 @@ public:
URL withNewSubPath (const String& newPath) const;
/** Returns a new URL that refers to a sub-path relative to this one.
E.g. if the URL is "http://www.xyz.com/foo" and you call this with
"bar", it'll return "http://www.xyz.com/foo/bar". Note that there's no way for
this method to know whether the original URL is a file or directory, so it's
@@ -134,7 +128,6 @@ public:
/** Returns a copy of this URL, with a GET or POST parameter added to the end.
Any control characters in the value will be encoded.
e.g. calling "withParameter ("amount", "some fish") for the url "www.fish.com"
would produce a new url whose toString(true) method would return
"www.fish.com?amount=some+fish".
@@ -241,20 +234,17 @@ public:
//==============================================================================
/** Tries to launch the system's default browser to open the URL.
Returns true if this seems to have worked.
*/
bool launchInDefaultBrowser() const;
//==============================================================================
/** Takes a guess as to whether a string might be a valid website address.
This isn't foolproof!
*/
static bool isProbablyAWebsiteURL (const String& possibleURL);
/** Takes a guess as to whether a string might be a valid email address.
This isn't foolproof!
*/
static bool isProbablyAnEmailAddress (const String& possibleEmailAddress);
@@ -319,7 +309,6 @@ public:
//==============================================================================
/** Represents a download task.
Returned by downloadToFile to allow querying and controling the download task.
*/
class DownloadTask
@@ -346,34 +335,32 @@ public:
/** Returns the total length of the download task. This may return -1 if the length
was not returned by the server. */
inline int64 getTotalLength() const { return contentLength; }
int64 getTotalLength() const { return contentLength; }
/** Returns the number of bytes that have been downloaded so far. */
inline int64 getLengthDownloaded() const { return downloaded; }
int64 getLengthDownloaded() const { return downloaded; }
/** Returns true if the download finished or there was an error. */
inline bool isFinished() const { return finished; }
/** Returns the status code of the server's response. This will only be valid
after the download has finished.
bool isFinished() const { return finished; }
/** Returns the status code of the server's response.
This will only be valid after the download has finished.
@see isFinished
*/
inline int statusCode() const { return httpCode; }
int statusCode() const { return httpCode; }
/** Returns true if there was an error. */
inline bool hadError() const { return error; }
protected:
int64 contentLength, downloaded;
bool finished, error;
int httpCode;
int64 contentLength = -1, downloaded = 0;
bool finished = false, error = false;
int httpCode = -1;
DownloadTask();
private:
friend class URL;
static DownloadTask* createFallbackDownloader (const URL&, const File&, const String&, Listener*, bool);
public:
@@ -381,6 +368,7 @@ public:
/** internal **/
static void juce_iosURLSessionNotify (const String&);
#endif
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DownloadTask)
};


Loading…
Cancel
Save