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

#include <platform.h>

#include <string>
#include <sstream>

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

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

#include "sdk/common/service/webserver_shared/inno_error_pages.h"
#include "sdk/common/service/webserver_shared/webserver_internal.h"
#include "sdk/common/service/webserver_shared/http_digest_host.h"
#include "sdk/common/service/webserver_shared/http_auth_digest.h"

#include "webserver_message_handler.h"
#include "webserver_digest_authenticator.h"

HTTPLib::http_request_method_t HandlerTypeToRequestType(msg_handler_type_t handlerType)
{
	HTTPLib::http_request_method_t result;
	switch (handlerType) {
	case MSG_HANDLER_GET: result = HTTPLib::HTTP_GET; break;
	case MSG_HANDLER_POST: result = HTTPLib::HTTP_POST; break;
	case MSG_HANDLER_COPY: result = HTTPLib::HTTP_COPY; break;
	case MSG_HANDLER_DELETE: result = HTTPLib::HTTP_DELETE; break;
	case MSG_HANDLER_MKCOL: result = HTTPLib::HTTP_MKCOL; break;
	case MSG_HANDLER_MOVE: result = HTTPLib::HTTP_MOVE; break;
	case MSG_HANDLER_PUT: result = HTTPLib::HTTP_PUT; break;
	case MSG_HANDLER_PROPFIND: result = HTTPLib::HTTP_PROPFIND; break;
	case MSG_HANDLER_OPTIONS: result = HTTPLib::HTTP_OPTIONS; break;
	case MSG_HANDLER_LOCK: result = HTTPLib::HTTP_LOCK; break;
	case MSG_HANDLER_UNLOCK: result = HTTPLib::HTTP_UNLOCK; break;
	case MSG_HANDLER_PROPPATCH: result = HTTPLib::HTTP_PROPPATCH; break;
	default: result = HTTPLib::HTTP_NONE; break;
	}
	return result;
}


WebserverDigestAuthenticator::WebserverDigestAuthenticator(HTTPAuthDigest * authDigest)
	: authDigest(authDigest)
{
}

WebserverDigestAuthenticator::~WebserverDigestAuthenticator()
{
}

void WebserverDigestAuthenticator::Init(WebserverMessageHandler * handler)
{
	this->messageHandler = handler;
	this->requestTarget = this->messageHandler->GetRequestTarget();
	this->parseSuccess = this->authDigest->ParseAuthField(handler->GetHeaderFieldValue("Authorization"), HandlerTypeToRequestType(handler->GetHandlerType()));
}

const char * WebserverDigestAuthenticator::User()
{
	return this->parseSuccess ? this->authDigest->GetUser() : nullptr;
}

const char * WebserverDigestAuthenticator::AuthenticationHeaderField()
{
	std::ostringstream s;
	digest_nonce_t dn;
	authDigest->ReadDigestNonce(dn);
	s << "Digest realm=\"" << this->messageHandler->GetDigestAuthRealm() << "\", qop=\"auth\", nonce=\"" << dn.nonce->GetNonce() << "\", opaque=\"" << this->authDigest->GetServerOpaque() << "\"";
	if (dn.needStale) s << ", stale=TRUE";
	this->authHeaderField = s.str();
	return authHeaderField.c_str();
}

bool WebserverDigestAuthenticator::IsAuthenticated(const char * user, const char * password)
{
	bool result;
	if (this->authDigest == nullptr || this->parseSuccess == false) result = false;
	else result = this->authDigest->VerifyAuthentication(user, password, this->requestTarget.c_str());
	return result;
}

void WebserverDigestAuthenticator::SendAuthenticationRequest()
{
	this->SendAuthenticationRequest(INNO_401, INNO_401_LEN);
}

void WebserverDigestAuthenticator::SendAuthenticationRequest(const char * body, size_t bodySize, wsr_type_t respopnseType)
{
	this->messageHandler->SetStatusCode(HTTP_STATUS_401, nullptr);
	this->messageHandler->SetTransferInfo(respopnseType, bodySize, wsr_flags_t::WSP_FLAG_NONE);
	this->messageHandler->SetHeaderField("WWW-Authenticate", this->AuthenticationHeaderField());
	this->messageHandler->Send(body, bodySize);
}
