
/*---------------------------------------------------------------------------*/
/* webserver_get_handler.h                                                   */
/* copyright (c) innovaphone 2016                                            */
/*                                                                           */
/*---------------------------------------------------------------------------*/

#include <platform.h>

#include "sdk/common/interface/webserver_plugin.h"

#include "sdk/common/lib/httplib.h"

#include "sdk/common/service/webserver_shared/webserver_internal.h"

#include "webserver_message_handler.h"
#include "webserver_get_handler.h"


WebserverGetHandler::WebserverGetHandler(UWebserverMessageHandler * baseUser,
                                         dword connectionID,
                                         byte * extHeaderBuffer,
                                         char * resourceName,
                                         char * resReqPath,
                                         class ExtendedHeader & extHeader,
                                         IWebserverMessage * const webserverMessageSend,
                                         IInstanceLog * const log,
                                         word protocolVersion)
    : WebserverMessageHandler("IWebserverGet", MSG_HANDLER_GET, baseUser, extHeaderBuffer, connectionID, 0, webserverMessageSend, resourceName, resReqPath, log, extHeader, protocolVersion)
{
    this->user = NULL;
    this->etag = connFlags.eTag && extHeader.ETag() != nullptr ? extHeader.ETag() : nullptr;
    this->rangeCount = extHeader.RangeCount();
    this->ranges = extHeader.RangesBuffer();
    this->httpRange = nullptr;
    this->range.rangeType = IWebserverGetRange::RANGE_NONE;
    this->range.start = this->range.end = 0;
}


WebserverGetHandler::~WebserverGetHandler()
{
    delete httpRange;
}


IWebserverGetRange * WebserverGetHandler::GetRange(size_t idx)
{
    this->log->Log(LOG_WEBSERVER_PLUGIN, "WebserverGetHandler(connection id: %u)::GetRange() idx: %u", this->connectionID, idx);
    
    ASSERT(idx <= rangeCount, "IWebserverGet::GetRange(): given index is out of range");
    byte * dataStart = ranges + (sizeof(byte) + sizeof(dword) * 2) * idx;
    this->range.rangeType = IWebserverGetRange::range_type_t(*dataStart);
    dataStart += sizeof(byte);
    if (this->protocolVersion == WEBSERVER_PROTOCOL_VERSION_0) {
        this->range.start = READ_DWORD_NET(dataStart);
        dataStart += sizeof(dword);
        this->range.end = READ_DWORD_NET(dataStart);
    }
    else {
        this->range.start = READ_QUAD_NET(dataStart);
        dataStart += sizeof(ulong64);
        this->range.end = READ_QUAD_NET(dataStart);

    }
    return &this->range;
}


void WebserverGetHandler::SetTransferRange(ulong64 start, ulong64 end)
{
    this->log->Log(LOG_WEBSERVER_PLUGIN, "WebserverGetHandler(connection id: %u)::SetTransferRange() start: %llu, end: %llu", this->connectionID, start, end);

    if (this->httpRange == nullptr) {
        this->httpRange = new HTTPRange;
        this->httpRange->start = start;
        this->httpRange->end = end;
        this->httpRange->rangeType = HTTPRange::RANGE_START_END;
        this->extHeader.SetRequestRange(this->httpRange, 1);
    }
    else debug->printf("WARNING: IWebserverGet::SetTransferRange() called multiple times!");
}


void WebserverGetHandler::ForceDownloadResponse(const char * fileName)
{
    this->log->Log(LOG_WEBSERVER_PLUGIN, "WebserverGetHandler(connection id: %u)::ForceDownloadResponse() fileName: '%s'", this->connectionID, fileName);

    char buffer[2048];
    char format[] = "attachment; filename=\"%s\"";
    if (fileName && (sizeof(format) - 3 + strlen(fileName) < sizeof(buffer))) {
        _sprintf(buffer, format, fileName);
        WebserverMessageHandler::SetHeaderField("Content-Disposition", buffer);
    }
    else WebserverMessageHandler::SetHeaderField("Content-Disposition", "attachment");
}
