2019-12-26 14:45:42 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
2019-01-08 11:38:48 -05:00
|
|
|
|
|
|
|
|
#include "GenericPlatform/HttpRequestPayload.h"
|
|
|
|
|
#include "GenericPlatform/GenericPlatformFile.h"
|
|
|
|
|
#include "GenericPlatform/GenericPlatformHttp.h"
|
2020-05-06 17:58:18 -04:00
|
|
|
#include "HAL/PlatformFileManager.h"
|
2019-01-08 11:38:48 -05:00
|
|
|
|
|
|
|
|
bool FGenericPlatformHttp::IsURLEncoded(const TArray<uint8>& Payload)
|
|
|
|
|
{
|
|
|
|
|
static char AllowedChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~";
|
|
|
|
|
static bool bTableFilled = false;
|
|
|
|
|
static bool AllowedTable[256] = { false };
|
|
|
|
|
|
|
|
|
|
if (!bTableFilled)
|
|
|
|
|
{
|
2019-09-28 08:19:35 -04:00
|
|
|
for (int32 Idx = 0; Idx < UE_ARRAY_COUNT(AllowedChars) - 1; ++Idx) // -1 to avoid trailing 0
|
2019-01-08 11:38:48 -05:00
|
|
|
{
|
|
|
|
|
uint8 AllowedCharIdx = static_cast<uint8>(AllowedChars[Idx]);
|
2019-09-28 08:19:35 -04:00
|
|
|
check(AllowedCharIdx < UE_ARRAY_COUNT(AllowedTable));
|
2019-01-08 11:38:48 -05:00
|
|
|
AllowedTable[AllowedCharIdx] = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bTableFilled = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int32 Num = Payload.Num();
|
|
|
|
|
for (int32 Idx = 0; Idx < Num; ++Idx)
|
|
|
|
|
{
|
|
|
|
|
if (!AllowedTable[Payload[Idx]])
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FRequestPayloadInFileStream::FRequestPayloadInFileStream(TSharedRef<FArchive, ESPMode::ThreadSafe> InFile) : File(InFile)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FRequestPayloadInFileStream::~FRequestPayloadInFileStream()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32 FRequestPayloadInFileStream::GetContentLength() const
|
|
|
|
|
{
|
|
|
|
|
return static_cast<int32>(File->TotalSize());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const TArray<uint8>& FRequestPayloadInFileStream::GetContent() const
|
|
|
|
|
{
|
|
|
|
|
ensureMsgf(false, TEXT("GetContent() on a streaming request payload is not allowed"));
|
|
|
|
|
static const TArray<uint8> NotSupported;
|
|
|
|
|
return NotSupported;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FRequestPayloadInFileStream::IsURLEncoded() const
|
|
|
|
|
{
|
|
|
|
|
// Assume that files are not URL encoded, because they probably aren't.
|
|
|
|
|
// This implies that POST requests with streamed files will need the caller to set a Content-Type.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t FRequestPayloadInFileStream::FillOutputBuffer(void* OutputBuffer, size_t MaxOutputBufferSize, size_t SizeAlreadySent)
|
|
|
|
|
{
|
2020-06-23 18:40:00 -04:00
|
|
|
return FillOutputBuffer(TArrayView<uint8>(static_cast<uint8*>(OutputBuffer), MaxOutputBufferSize), SizeAlreadySent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t FRequestPayloadInFileStream::FillOutputBuffer(TArrayView<uint8> OutputBuffer, size_t SizeAlreadySent)
|
|
|
|
|
{
|
|
|
|
|
const size_t ContentLength = static_cast<size_t>(GetContentLength());
|
2019-01-08 11:38:48 -05:00
|
|
|
check(SizeAlreadySent <= ContentLength);
|
2020-06-23 18:40:00 -04:00
|
|
|
const size_t SizeToSend = ContentLength - SizeAlreadySent;
|
|
|
|
|
const size_t SizeToSendThisTime = FMath::Min(SizeToSend, static_cast<size_t>(OutputBuffer.Num()));
|
2019-01-08 11:38:48 -05:00
|
|
|
if (SizeToSendThisTime != 0)
|
|
|
|
|
{
|
2020-06-23 18:40:00 -04:00
|
|
|
if (File->Tell() != SizeAlreadySent)
|
2019-01-08 11:38:48 -05:00
|
|
|
{
|
|
|
|
|
File->Seek(SizeAlreadySent);
|
|
|
|
|
}
|
2020-06-23 18:40:00 -04:00
|
|
|
File->Serialize(OutputBuffer.GetData(), static_cast<int64>(SizeToSendThisTime));
|
2019-01-08 11:38:48 -05:00
|
|
|
}
|
|
|
|
|
return SizeToSendThisTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FRequestPayloadInMemory::FRequestPayloadInMemory(const TArray<uint8>& Array) : Buffer(Array)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-28 16:10:55 -04:00
|
|
|
FRequestPayloadInMemory::FRequestPayloadInMemory(TArray<uint8>&& Array) : Buffer(MoveTemp(Array))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-08 11:38:48 -05:00
|
|
|
FRequestPayloadInMemory::~FRequestPayloadInMemory()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32 FRequestPayloadInMemory::GetContentLength() const
|
|
|
|
|
{
|
|
|
|
|
return Buffer.Num();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const TArray<uint8>& FRequestPayloadInMemory::GetContent() const
|
|
|
|
|
{
|
|
|
|
|
return Buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FRequestPayloadInMemory::IsURLEncoded() const
|
|
|
|
|
{
|
|
|
|
|
return FGenericPlatformHttp::IsURLEncoded(Buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t FRequestPayloadInMemory::FillOutputBuffer(void* OutputBuffer, size_t MaxOutputBufferSize, size_t SizeAlreadySent)
|
|
|
|
|
{
|
2020-06-23 18:40:00 -04:00
|
|
|
return FillOutputBuffer(TArrayView<uint8>(static_cast<uint8*>(OutputBuffer), MaxOutputBufferSize), SizeAlreadySent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t FRequestPayloadInMemory::FillOutputBuffer(TArrayView<uint8> OutputBuffer, size_t SizeAlreadySent)
|
|
|
|
|
{
|
|
|
|
|
const size_t ContentLength = static_cast<size_t>(Buffer.Num());
|
2019-01-08 11:38:48 -05:00
|
|
|
check(SizeAlreadySent <= ContentLength);
|
2020-06-23 18:40:00 -04:00
|
|
|
const size_t SizeToSend = ContentLength - SizeAlreadySent;
|
|
|
|
|
const size_t SizeToSendThisTime = FMath::Min(SizeToSend, static_cast<size_t>(OutputBuffer.Num()));
|
2019-01-08 11:38:48 -05:00
|
|
|
if (SizeToSendThisTime != 0)
|
|
|
|
|
{
|
2020-06-23 18:40:00 -04:00
|
|
|
FMemory::Memcpy(OutputBuffer.GetData(), Buffer.GetData() + SizeAlreadySent, SizeToSendThisTime);
|
2019-01-08 11:38:48 -05:00
|
|
|
}
|
|
|
|
|
return SizeToSendThisTime;
|
|
|
|
|
}
|