|
|
@@ -25,14 +25,15 @@ namespace juce |
|
|
|
|
|
|
|
void MACAddress::findAllAddresses (Array<MACAddress>& result)
|
|
|
|
{
|
|
|
|
const int s = socket (AF_INET, SOCK_DGRAM, 0);
|
|
|
|
auto s = socket (AF_INET, SOCK_DGRAM, 0);
|
|
|
|
|
|
|
|
if (s != -1)
|
|
|
|
{
|
|
|
|
struct ifaddrs* addrs = nullptr;
|
|
|
|
|
|
|
|
if (getifaddrs (&addrs) != -1)
|
|
|
|
{
|
|
|
|
for (struct ifaddrs* i = addrs; i != nullptr; i = i->ifa_next)
|
|
|
|
for (auto* i = addrs; i != nullptr; i = i->ifa_next)
|
|
|
|
{
|
|
|
|
struct ifreq ifr;
|
|
|
|
strcpy (ifr.ifr_name, i->ifa_name);
|
|
|
@@ -69,7 +70,7 @@ bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& /* targetEma |
|
|
|
class WebInputStream::Pimpl
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Pimpl (WebInputStream& pimplOwner, const URL& urlToCopy, const bool shouldUsePost)
|
|
|
|
Pimpl (WebInputStream& pimplOwner, const URL& urlToCopy, bool shouldUsePost)
|
|
|
|
: owner (pimplOwner), url (urlToCopy),
|
|
|
|
isPost (shouldUsePost), httpRequestCmd (shouldUsePost ? "POST" : "GET")
|
|
|
|
{}
|
|
|
@@ -95,19 +96,21 @@ public: |
|
|
|
void withCustomRequestCommand (const String& customRequestCommand) { httpRequestCmd = customRequestCommand; }
|
|
|
|
void withConnectionTimeout (int timeoutInMs) { timeOutMs = timeoutInMs; }
|
|
|
|
void withNumRedirectsToFollow (int maxRedirectsToFollow) { numRedirectsToFollow = maxRedirectsToFollow; }
|
|
|
|
int getStatusCode() const { return statusCode; }
|
|
|
|
StringPairArray getRequestHeaders() const { return WebInputStream::parseHttpHeaders (headers); }
|
|
|
|
|
|
|
|
StringPairArray getResponseHeaders() const
|
|
|
|
{
|
|
|
|
StringPairArray responseHeaders;
|
|
|
|
|
|
|
|
if (! isError())
|
|
|
|
{
|
|
|
|
for (int i = 0; i < headerLines.size(); ++i)
|
|
|
|
{
|
|
|
|
const String& headersEntry = headerLines[i];
|
|
|
|
const String key (headersEntry.upToFirstOccurrenceOf (": ", false, false));
|
|
|
|
const String value (headersEntry.fromFirstOccurrenceOf (": ", false, false));
|
|
|
|
const String previousValue (responseHeaders [key]);
|
|
|
|
auto& headersEntry = headerLines[i];
|
|
|
|
auto key = headersEntry.upToFirstOccurrenceOf (": ", false, false);
|
|
|
|
auto value = headersEntry.fromFirstOccurrenceOf (": ", false, false);
|
|
|
|
auto previousValue = responseHeaders[key];
|
|
|
|
responseHeaders.set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -115,8 +118,6 @@ public: |
|
|
|
return responseHeaders;
|
|
|
|
}
|
|
|
|
|
|
|
|
int getStatusCode() const { return statusCode; }
|
|
|
|
|
|
|
|
bool connect (WebInputStream::Listener* listener)
|
|
|
|
{
|
|
|
|
{
|
|
|
@@ -129,7 +130,7 @@ public: |
|
|
|
address = url.toString (! isPost);
|
|
|
|
statusCode = createConnection (listener, numRedirectsToFollow);
|
|
|
|
|
|
|
|
return (statusCode != 0);
|
|
|
|
return statusCode != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cancel()
|
|
|
@@ -137,7 +138,6 @@ public: |
|
|
|
const ScopedLock lock (createSocketLock);
|
|
|
|
|
|
|
|
hasBeenCancelled = true;
|
|
|
|
|
|
|
|
statusCode = -1;
|
|
|
|
finished = true;
|
|
|
|
|
|
|
@@ -190,7 +190,7 @@ public: |
|
|
|
chunkLengthBuffer.writeByte (c);
|
|
|
|
}
|
|
|
|
|
|
|
|
const int64 chunkSize = chunkLengthBuffer.toString().trimStart().getHexValue64();
|
|
|
|
auto chunkSize = chunkLengthBuffer.toString().trimStart().getHexValue64();
|
|
|
|
|
|
|
|
if (chunkSize == 0)
|
|
|
|
{
|
|
|
@@ -216,7 +216,8 @@ public: |
|
|
|
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
|
|
|
|
return 0; // (timeout)
|
|
|
|
|
|
|
|
const int bytesRead = jmax (0, (int) recv (socketHandle, buffer, (size_t) bytesToRead, MSG_WAITALL));
|
|
|
|
auto bytesRead = jmax (0, (int) recv (socketHandle, buffer, (size_t) bytesToRead, MSG_WAITALL));
|
|
|
|
|
|
|
|
if (bytesRead == 0)
|
|
|
|
finished = true;
|
|
|
|
|
|
|
@@ -238,7 +239,7 @@ public: |
|
|
|
if (wantedPos < position)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
int64 numBytesToSkip = wantedPos - position;
|
|
|
|
auto numBytesToSkip = wantedPos - position;
|
|
|
|
auto skipBufferSize = (int) jmin (numBytesToSkip, (int64) 16384);
|
|
|
|
HeapBlock<char> temp (skipBufferSize);
|
|
|
|
|
|
|
@@ -286,14 +287,14 @@ private: |
|
|
|
levelsOfRedirection = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int createConnection (WebInputStream::Listener* listener, const int numRedirects)
|
|
|
|
int createConnection (WebInputStream::Listener* listener, int numRedirects)
|
|
|
|
{
|
|
|
|
closeSocket (false);
|
|
|
|
|
|
|
|
if (isPost)
|
|
|
|
WebInputStream::createHeadersAndPostData (url, headers, postData);
|
|
|
|
|
|
|
|
uint32 timeOutTime = Time::getMillisecondCounter();
|
|
|
|
auto timeOutTime = Time::getMillisecondCounter();
|
|
|
|
|
|
|
|
if (timeOutMs == 0)
|
|
|
|
timeOutMs = 30000;
|
|
|
@@ -305,6 +306,7 @@ private: |
|
|
|
|
|
|
|
String hostName, hostPath;
|
|
|
|
int hostPort;
|
|
|
|
|
|
|
|
if (! decomposeURL (address, hostName, hostPath, hostPort))
|
|
|
|
return 0;
|
|
|
|
|
|
|
@@ -312,7 +314,8 @@ private: |
|
|
|
int proxyPort = 0;
|
|
|
|
int port = 0;
|
|
|
|
|
|
|
|
const String proxyURL (getenv ("http_proxy"));
|
|
|
|
auto proxyURL = String::fromUTF8 (getenv ("http_proxy"));
|
|
|
|
|
|
|
|
if (proxyURL.startsWithIgnoreCase ("http://"))
|
|
|
|
{
|
|
|
|
if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort))
|
|
|
@@ -335,6 +338,7 @@ private: |
|
|
|
hints.ai_flags = AI_NUMERICSERV;
|
|
|
|
|
|
|
|
struct addrinfo* result = nullptr;
|
|
|
|
|
|
|
|
if (getaddrinfo (serverName.toUTF8(), String (port).toUTF8(), &hints, &result) != 0 || result == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
@@ -379,17 +383,17 @@ private: |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
String responseHeader (readResponse (timeOutTime));
|
|
|
|
auto responseHeader = readResponse (timeOutTime);
|
|
|
|
position = 0;
|
|
|
|
|
|
|
|
if (responseHeader.isNotEmpty())
|
|
|
|
{
|
|
|
|
headerLines = StringArray::fromLines (responseHeader);
|
|
|
|
|
|
|
|
const int status = responseHeader.fromFirstOccurrenceOf (" ", false, false)
|
|
|
|
.substring (0, 3).getIntValue();
|
|
|
|
auto status = responseHeader.fromFirstOccurrenceOf (" ", false, false)
|
|
|
|
.substring (0, 3).getIntValue();
|
|
|
|
|
|
|
|
String location (findHeaderItem (headerLines, "Location:"));
|
|
|
|
auto location = findHeaderItem (headerLines, "Location:");
|
|
|
|
|
|
|
|
if (++levelsOfRedirection <= numRedirects
|
|
|
|
&& status >= 300 && status < 400
|
|
|
@@ -410,7 +414,7 @@ private: |
|
|
|
return createConnection (listener, numRedirects);
|
|
|
|
}
|
|
|
|
|
|
|
|
String contentLengthString (findHeaderItem (headerLines, "Content-Length:"));
|
|
|
|
auto contentLengthString = findHeaderItem (headerLines, "Content-Length:");
|
|
|
|
|
|
|
|
if (contentLengthString.isNotEmpty())
|
|
|
|
contentLength = contentLengthString.getLargeIntValue();
|
|
|
@@ -425,7 +429,7 @@ private: |
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
String readResponse (const uint32 timeOutTime)
|
|
|
|
String readResponse (uint32 timeOutTime)
|
|
|
|
{
|
|
|
|
int numConsecutiveLFs = 0;
|
|
|
|
MemoryOutputStream buffer;
|
|
|
@@ -436,6 +440,7 @@ private: |
|
|
|
&& ! (finished || isError()))
|
|
|
|
{
|
|
|
|
char c = 0;
|
|
|
|
|
|
|
|
if (read (&c, 1) != 1)
|
|
|
|
return {};
|
|
|
|
|
|
|
@@ -447,7 +452,7 @@ private: |
|
|
|
numConsecutiveLFs = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const String header (buffer.toString().trimEnd());
|
|
|
|
auto header = buffer.toString().trimEnd();
|
|
|
|
|
|
|
|
if (header.startsWithIgnoreCase ("HTTP/"))
|
|
|
|
return header;
|
|
|
@@ -471,11 +476,11 @@ private: |
|
|
|
dest << ':' << port;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MemoryBlock createRequestHeader (const String& hostName, const int hostPort,
|
|
|
|
const String& proxyName, const int proxyPort,
|
|
|
|
static MemoryBlock createRequestHeader (const String& hostName, int hostPort,
|
|
|
|
const String& proxyName, int proxyPort,
|
|
|
|
const String& hostPath, const String& originalURL,
|
|
|
|
const String& userHeaders, const MemoryBlock& postData,
|
|
|
|
const bool isPost, const String& httpRequestCmd)
|
|
|
|
bool isPost, const String& httpRequestCmd)
|
|
|
|
{
|
|
|
|
MemoryOutputStream header;
|
|
|
|
|
|
|
@@ -503,7 +508,7 @@ private: |
|
|
|
return header.getMemoryBlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool sendHeader (int socketHandle, const MemoryBlock& requestHeader, const uint32 timeOutTime,
|
|
|
|
static bool sendHeader (int socketHandle, const MemoryBlock& requestHeader, uint32 timeOutTime,
|
|
|
|
WebInputStream& pimplOwner, WebInputStream::Listener* listener)
|
|
|
|
{
|
|
|
|
size_t totalHeaderSent = 0;
|
|
|
@@ -513,7 +518,7 @@ private: |
|
|
|
if (Time::getMillisecondCounter() > timeOutTime)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const int numToSend = jmin (1024, (int) (requestHeader.getSize() - totalHeaderSent));
|
|
|
|
auto numToSend = jmin (1024, (int) (requestHeader.getSize() - totalHeaderSent));
|
|
|
|
|
|
|
|
if (send (socketHandle, static_cast<const char*> (requestHeader.getData()) + totalHeaderSent, (size_t) numToSend, 0) != numToSend)
|
|
|
|
return false;
|
|
|
@@ -532,8 +537,9 @@ private: |
|
|
|
if (! url.startsWithIgnoreCase ("http://"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const int nextSlash = url.indexOfChar (7, '/');
|
|
|
|
int nextColon = url.indexOfChar (7, ':');
|
|
|
|
auto nextSlash = url.indexOfChar (7, '/');
|
|
|
|
auto nextColon = url.indexOfChar (7, ':');
|
|
|
|
|
|
|
|
if (nextColon > nextSlash && nextSlash > 0)
|
|
|
|
nextColon = -1;
|
|
|
|
|
|
|
|