33 :
Thread (
"DownloadTask thread"),
40 jassert (fileStream !=
nullptr);
43 targetLocation = fileStream->getFile();
44 contentLength = stream->getTotalLength();
45 httpCode = stream->getStatusCode();
62 if (listener !=
nullptr)
63 listener->
progress (
this, downloaded, contentLength);
66 :
static_cast<int64> (contentLength - downloaded));
68 auto actual = stream->read (buffer.
get(), max);
73 if (! fileStream->write (buffer.
get(),
static_cast<size_t> (
actual)))
81 if (downloaded == contentLength)
90 if (contentLength > 0 && downloaded < contentLength)
102 const size_t bufferSize;
116 const size_t bufferSize = 0x8000;
121 auto stream = std::make_unique<WebInputStream> (
urlToUse, options.usePost);
122 stream->withExtraHeaders (options.extraHeaders);
124 if (stream->connect (
nullptr))
125 return std::make_unique<FallbackDownloadTask> (std::move (
outputStream),
134URL::DownloadTask::DownloadTask() {}
174 url =
"file://" + url;
217URL::URL (
const String& u,
int) : url (u) {}
226 return url ==
other.url
227 && postData ==
other.postData
228 && parameterNames ==
other.parameterNames
229 && parameterValues ==
other.parameterValues
230 && filesToUpload ==
other.filesToUpload;
233bool URL::operator!= (
const URL&
other)
const
240 static String getMangledParameters (
const URL& url)
242 jassert (url.getParameterNames().size() == url.getParameterValues().size());
245 for (
int i = 0; i < url.getParameterNames().size(); ++i)
250 auto val = url.getParameterValues()[i];
254 if (
val.isNotEmpty())
261 static int findEndOfScheme (
const String& url)
266 || url[i] ==
'+' || url[i] ==
'-' || url[i] ==
'.')
269 return url.substring (i).startsWith (
"://") ? i + 1 : 0;
272 static int findStartOfNetLocation (
const String& url)
274 int start = findEndOfScheme (url);
276 while (url[start] ==
'/')
282 static int findStartOfPath (
const String& url)
284 return url.indexOfChar (findStartOfNetLocation (url),
'/') + 1;
287 static void concatenatePaths (String& path,
const String& suffix)
289 if (! path.endsWithChar (
'/'))
292 if (suffix.startsWithChar (
'/'))
293 path += suffix.substring (1);
298 static String removeLastPathSection (
const String& url)
301 auto lastSlash = url.lastIndexOfChar (
'/');
304 return removeLastPathSection (url.dropLastCharacters (1));
313void URL::addParameter (
const String& name,
const String& value)
315 parameterNames.
add (name);
316 parameterValues.
add (value);
329 return url.isEmpty();
335 return url.isNotEmpty();
340 return getDomainInternal (
false);
345 auto startOfPath = URLHelpers::findStartOfPath (url);
359 if (parameterNames.
size() > 0)
360 result +=
"?" + URLHelpers::getMangledParameters (*
this);
378 return url.
substring (0, URLHelpers::findEndOfScheme (url) - 1);
389 return fileFromFileSchemeURL (*
this);
398URL::ParameterHandling URL::toHandling (
bool usePostData)
400 return usePostData ? ParameterHandling::inPostData : ParameterHandling::inAddress;
403File URL::fileFromFileSchemeURL (
const URL&
fileURL)
426 path =
"\\\\" + path;
450 auto startOfPath = URLHelpers::findStartOfPath (url);
455 URLHelpers::concatenatePaths (u.url,
newPath);
462 u.url = URLHelpers::removeLastPathSection (u.url);
469 URLHelpers::concatenatePaths (u.url,
subPath);
473bool URL::hasBodyDataToSend()
const
475 return filesToUpload.
size() > 0 || ! postData.
isEmpty();
478void URL::createHeadersAndPostData (String& headers,
484 if (filesToUpload.
size() > 0)
491 headers <<
"Content-Type: multipart/form-data; boundary=" <<
boundary <<
"\r\n";
495 for (
int i = 0; i < parameterNames.
size(); ++i)
497 data <<
"\r\nContent-Disposition: form-data; name=\"" << parameterNames[i]
498 <<
"\"\r\n\r\n" << parameterValues[i]
502 for (
auto* f : filesToUpload)
504 data <<
"\r\nContent-Disposition: form-data; name=\"" << f->parameterName
505 <<
"\"; filename=\"" << f->filename <<
"\"\r\n";
507 if (f->mimeType.isNotEmpty())
508 data <<
"Content-Type: " << f->mimeType <<
"\r\n";
510 data <<
"Content-Transfer-Encoding: binary\r\n\r\n";
512 if (f->data !=
nullptr)
525 data << URLHelpers::getMangledParameters (*
this);
530 if (! headers.containsIgnoreCase (
"Content-Type"))
531 headers <<
"Content-Type: application/x-www-form-urlencoded\r\n";
533 headers <<
"Content-length: " << (
int)
data.getDataSize() <<
"\r\n";
540 for (
auto*
protocol : {
"http:",
"https:",
"ftp:" })
548 .fromLastOccurrenceOf (
".",
false,
false);
564 auto start = URLHelpers::findStartOfNetLocation (url);
565 auto end1 = url.indexOfChar (start,
'/');
571 return url.substring (start,
end);
579URL::Bookmark::~Bookmark()
586 u.bookmark =
new URL::Bookmark (
bookmark);
591 if (u.bookmark.get() ==
nullptr)
594 return u.bookmark.get()->data;
600template <
typename Stream>
611 iOSFileStreamWrapperFlush<Stream>::flush (
this);
690template <
typename Member,
typename Item>
691static URL::InputStreamOptions with (URL::InputStreamOptions options,
Member&&
member, Item&& item)
693 options.*
member = std::forward<Item> (item);
701 return with (*
this, &InputStreamOptions::progressCallback, std::move (
cb));
706 return with (*
this, &InputStreamOptions::extraHeaders, headers);
711 return with (*
this, &InputStreamOptions::connectionTimeOutMs, timeout);
716 return with (*
this, &InputStreamOptions::responseHeaders, headers);
721 return with (*
this, &InputStreamOptions::statusCode, status);
726 return with (*
this, &InputStreamOptions::numRedirectsToFollow,
numRedirects);
731 return with (*
this, &InputStreamOptions::httpRequestCmd,
cmd);
741 return std::make_unique<iOSFileStreamWrapper<FileInputStream>> (
const_cast<URL&
> (*this));
749 const auto usePost = options.getParameterHandling() == ParameterHandling::inPostData;
750 auto stream = std::make_unique<WebInputStream> (*
this, usePost);
752 auto extraHeaders = options.getExtraHeaders();
754 if (extraHeaders.isNotEmpty())
755 stream->withExtraHeaders (extraHeaders);
757 auto timeout = options.getConnectionTimeoutMs();
760 stream->withConnectionTimeout (timeout);
762 auto requestCmd = options.getHttpRequestCmd();
765 stream->withCustomRequestCommand (
requestCmd);
767 stream->withNumRedirectsToFollow (options.getNumRedirectsToFollow());
774 ProgressCallbackCaller (
std::function<
bool (
int,
int)> progressCallbackToUse)
775 : callback (std::move (progressCallbackToUse))
779 bool postDataSendProgress (
WebInputStream&,
int bytesSent,
int totalBytes)
override
781 return callback (bytesSent, totalBytes);
789 if (
auto progressCallback = options.getProgressCallback())
790 return std::make_unique<ProgressCallbackCaller> (progressCallback);
797 if (
auto* status = options.getStatusCode())
800 if (
auto* responseHeaders = options.getResponseHeaders())
807 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wredundant-move")
809 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
823 return std::make_unique<iOSFileStreamWrapper<FileOutputStream>> (
const_cast<URL&
> (*this));
825 return std::make_unique<FileOutputStream> (
getLocalFile());
840 in->readIntoMemoryBlock (destData);
853 return in->readEntireStreamAsString();
903URL::Upload::Upload (
const String& param,
const String& name,
905 : parameterName (param), filename (name), mimeType (
mime), file (f), data (
mb)
907 jassert (mimeType.isNotEmpty());
910URL URL::withUpload (Upload*
const f)
const
914 for (
int i = u.filesToUpload.size(); --i >= 0;)
915 if (u.filesToUpload.getObjectPointerUnchecked (i)->parameterName == f->parameterName)
916 u.filesToUpload.remove (i);
918 u.filesToUpload.add (f);
923 const String& mimeType)
const
925 return withUpload (
new Upload (parameterName,
fileToUpload.getFileName(),
932 return withUpload (
new Upload (parameterName, filename, mimeType,
File(),
941 if (! result.containsChar (
'%'))
946 Array<char> utf8 (result.toRawUTF8(), (
int) result.getNumBytesAsUTF8());
948 for (
int i = 0; i <
utf8.size(); ++i)
950 if (
utf8.getUnchecked (i) ==
'%')
958 utf8.removeRange (i + 1, 2);
976 for (
int i = 0; i <
utf8.size(); ++i)
978 auto c =
utf8.getUnchecked (i);
984 utf8.insert (++i,
"0123456789ABCDEF" [((
uint8) c) >> 4]);
985 utf8.insert (++i,
"0123456789ABCDEF" [c & 15]);
997 if (u.containsChar (
'@') && ! u.containsChar (
':'))
1011 int numRedirectsToFollow,
1012 String httpRequestCmd)
const
1020 .withProgressCallback (std::move (callback))
1021 .withExtraHeaders (headers)
1022 .withConnectionTimeoutMs (timeOutMs)
1023 .withResponseHeaders (responseHeaders)
1024 .withStatusCode (statusCode)
1025 .withNumRedirectsToFollow (numRedirectsToFollow)
1026 .withHttpRequestCmd (httpRequestCmd));
1035 .withListener (listener)
static AndroidDocument fromDocument(const URL &documentUrl)
Create an AndroidDocument representing a single document.
std::unique_ptr< OutputStream > createOutputStream() const
Creates a stream for writing to this document.
Holds a resizable array of primitive or copy-by-value objects.
static int getHexDigitValue(juce_wchar digit) noexcept
Returns 0 to 16 for '0' to 'F", or -1 for characters that aren't a legal hex digit.
static bool isLetterOrDigit(char character) noexcept
Checks whether a character is alphabetic or numeric.
Represents a local file or directory.
static StringRef getSeparatorString()
The system-specific file separator character, as a string.
std::unique_ptr< FileInputStream > createInputStream() const
Creates a stream to read from this file.
Very simple container class to hold a pointer to some data on the heap.
ElementType * get() const noexcept
Returns a raw pointer to the allocated data.
A class to hold a resizable block of raw data.
bool isEmpty() const noexcept
Returns true if the memory block has zero size.
static bool JUCE_CALLTYPE openDocument(const String &documentURL, const String ¶meters)
Tries to launch the OS's default reader application for a given file or URL.
static Random & getSystemRandom() noexcept
The overhead of creating a new Random object is fairly small, but if you want to avoid it,...
int size() const noexcept
Returns the current number of objects in the array.
static StringArray fromTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Returns an array containing the tokens in a given string.
int size() const noexcept
Returns the number of strings in the array.
void add(String stringToAdd)
Appends a string at the end of the array.
A container for holding a set of strings which are keyed by another string.
int indexOfChar(juce_wchar characterToLookFor) const noexcept
Searches for a character inside this string.
String upToFirstOccurrenceOf(StringRef substringToEndWith, bool includeSubStringInResult, bool ignoreCase) const
Returns the start of this string, up to the first occurrence of a substring.
const char * toRawUTF8() const
Returns a pointer to a UTF-8 version of this string.
bool startsWithChar(juce_wchar character) const noexcept
Tests whether the string begins with a particular character.
size_t getNumBytesAsUTF8() const noexcept
Returns the number of bytes required to represent this string as UTF8.
static String toHexString(IntegerType number)
Returns a string representing this numeric value in hexadecimal.
String replace(StringRef stringToReplace, StringRef stringToInsertInstead, bool ignoreCase=false) const
Replaces all occurrences of a substring with another string.
String replaceCharacter(juce_wchar characterToReplace, juce_wchar characterToInsertInstead) const
Returns a string with all occurrences of a character replaced with a different one.
String substring(int startIndex, int endIndex) const
Returns a subsection of the string.
String fromLastOccurrenceOf(StringRef substringToFind, bool includeSubStringInResult, bool ignoreCase) const
Returns a section of the string starting from the last occurrence of a given substring.
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
Creates a String from a UTF-8 encoded buffer.
bool isNotEmpty() const noexcept
Returns true if the string contains at least one character.
String fromFirstOccurrenceOf(StringRef substringToStartFrom, bool includeSubStringInResult, bool ignoreCase) const
Returns a section of the string starting from a given substring.
bool waitForThreadToExit(int timeOutMilliseconds) const
Waits for the thread to stop.
bool startThread()
Attempts to start a new thread with default ('Priority::normal') priority.
bool threadShouldExit() const
Checks whether the thread has been told to stop running.
void signalThreadShouldExit()
Sets a flag to tell the thread it should stop.
Holds options that can be specified when starting a new download with downloadToFile().
auto withExtraHeaders(String value) const
Specifies headers to add to the request.
Represents a download task.
virtual ~DownloadTask()
Releases the resources of the download task, unregisters the listener and cancels the download if nec...
Represents a URL and has a bunch of useful functions to manipulate it.
URL withParameter(const String ¶meterName, const String ¶meterValue) const
Returns a copy of this URL, with a GET or POST parameter added to the end.
static URL createWithoutParsing(const String &url)
Returns a URL without attempting to remove any embedded parameters from the string.
File getLocalFile() const
Returns the file path of the local file to which this URL refers to.
bool isWellFormed() const
True if it seems to be valid.
bool readEntireBinaryStream(MemoryBlock &destData, bool usePostCommand=false) const
Tries to download the entire contents of this URL into a binary data block.
int getPort() const
Attempts to read a port number from the URL.
URL withDataToUpload(const String ¶meterName, const String &filename, const MemoryBlock &fileContentToUpload, const String &mimeType) const
Returns a copy of this URL, with a file-upload type parameter added to it.
String getFileName() const
Returns the file name.
URL getChildURL(const String &subPath) const
Returns a new URL that refers to a sub-path relative to this one.
static String removeEscapeChars(const String &stringToRemoveEscapeCharsFrom)
Replaces any escape character sequences in a string with their original character codes.
String getAnchorString() const
If any anchor is set, returns URL-encoded anchor, including the "#" prefix.
static String addEscapeChars(const String &stringToAddEscapeCharsTo, bool isParameter, bool roundBracketsAreLegal=true)
Adds escape sequences to a string to encode any characters that aren't legal in a URL.
URL withAnchor(const String &anchor) const
Returns a copy of this URL, with an anchor added to the end of the URL.
String toString(bool includeGetParameters) const
Returns a string version of the URL.
std::unique_ptr< OutputStream > createOutputStream() const
Attempts to open an output stream to a URL for writing.
String getSubPath(bool includeGetParameters=false) const
Returns the path part of the URL.
URL getParentURL() const
Attempts to return a URL which is the parent folder containing this URL.
String getQueryString() const
If any parameters are set, returns these URL-encoded, including the "?" prefix.
URL withNewSubPath(const String &newPath) const
Returns a new version of this URL with a different sub-path.
static bool isProbablyAnEmailAddress(const String &possibleEmailAddress)
Takes a guess as to whether a string might be a valid email address.
URL withNewDomainAndPath(const String &newFullPath) const
Returns a new version of this URL with a different domain and path.
String readEntireTextStream(bool usePostCommand=false) const
Tries to download the entire contents of this URL as a string.
bool isEmpty() const noexcept
Returns true if the URL is an empty string.
static bool isProbablyAWebsiteURL(const String &possibleURL)
Takes a guess as to whether a string might be a valid website address.
std::unique_ptr< InputStream > createInputStream(const InputStreamOptions &options) const
Attempts to open a stream that can read from this URL.
std::unique_ptr< DownloadTask > downloadToFile(const File &targetLocation, String extraHeaders=String(), DownloadTaskListener *listener=nullptr, bool usePostCommand=false)
This function is replaced by a new overload accepting a DownloadTaskOptions argument.
String getDomain() const
Returns just the domain part of the URL.
bool isLocalFile() const
Returns true if this URL refers to a local file.
URL withFileToUpload(const String ¶meterName, const File &fileToUpload, const String &mimeType) const
Returns a copy of this URL, with a file-upload type parameter added to it.
URL withPOSTData(const String &postData) const
Returns a copy of this URL, with a block of data to send as the POST data.
URL withParameters(const StringPairArray ¶metersToAdd) const
Returns a copy of this URL, with a set of GET or POST parameters added.
std::unique_ptr< XmlElement > readEntireXmlStream(bool usePostCommand=false) const
Tries to download the entire contents of this URL and parse it as XML.
String getScheme() const
Returns the scheme of the URL.
bool operator==(const URL &) const
Compares two URLs.
bool launchInDefaultBrowser() const
Tries to launch the system's default browser to open the URL.
URL()
Creates an empty URL.
wchar_t juce_wchar
A platform-independent 32-bit unicode character type.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
RangedDirectoryIterator end(const RangedDirectoryIterator &)
Returns a default-constructed sentinel value.
std::unique_ptr< XmlElement > parseXML(const String &textToParse)
Attempts to parse some XML text, returning a new XmlElement if it was valid.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
unsigned char uint8
A platform-independent 8-bit unsigned integer type.
long long int64
A platform-independent 64-bit integer type.
void run() override
Must be implemented to perform the thread's actual code.
Used to receive callbacks for download progress.
virtual void finished(DownloadTask *task, bool success)=0
Called when the download has finished.
virtual void progress(DownloadTask *task, int64 bytesDownloaded, int64 totalLength)
Called periodically by the OS to indicate download progress.